人与人之间的单机五子棋


每博一文案

作家苏曾说,到了现在这个年纪,谁都不想再取悦了,跟谁在一起舒服就和
谁在一起,包括朋友也是,累了,就躲远一点。人活着总是离不开圈子二字。
为了扩大自己的社交圈,参见各种活动,每天觥筹交错,忙得不亦乐乎?
可是,当我们心情低落的时候,把通讯录翻了个遍,也没找到一个能倾诉的人。
当我们遇到麻烦,想要求助,那些所谓的朋友,愿意帮忙的寥寥无几,以前
总觉得圈子越大越好,朋友越多越好。后来,慢慢发现,真正的朋友,再好,不再多。
越简单的人,越难交心,越简单的关系,越难长久。_________    一禅心灵庙语

文章目录

  • 人与人之间的单机五子棋
  • 每博一文案
  • 五子棋
  • 创建项目的注意事项
  • 五子棋实现原理解剖
  • 功能上简单细节构思
  • 定义相关的变量
  • 进入游戏的选择
  • 打印菜单的功能的实现
  • 游戏函数 Game( ) 的构建
  • 打印棋盘showBoard() 函数
  • 下棋playerMove( )函数
  • 判断胜负isOver( )函数
  • 计算坐标周围连续的个数chessCount( )函数
  • 五子棋完整代码实现
    • game.h
    • game.c
    • test.c
  • 最后:

五子棋

五子棋起源于中国,是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连珠者获胜。

五子棋容易上手,老少皆宜,而且趣味横生,引人入胜。它不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。


而我们做成后的样子是如下: 显示


创建项目的注意事项

  • 首先我们要明白一点就是不存在没有完完全全BUG的项目,就像人无完人一样 我们只能不断地对项目进行优化,减少BUG 的出现,但是我们好像并不能完全的消除所有的BUG
  • 而消除bug 的最好的方式就是运行测试+调试
  • 而我们在运行测试+调试 的时候,需要我们控制一定的量 ,我们需要把握住这个量 ,这一点是十分重要的,这样有助于我们快速的发现问题,也就是bug 的所在,从而提高我们的效率,减少我们的bug 的出现
  • 具体的方法,我个人有以下建议:
  1. 首先我们需要对项目进行合理的分类,那个类,那个文件实现什么样的功能: 比如:一个类是用于定义什么类型,方法的 ,另一个类是用于什么头main 的,再另外一个类是用于对于什么功能上的实现的 ,合理的分类,可以提高我们项目的可读性,让我们自身不会因为自己随着代码量的增加,对应功能上的增加而导致我们越敲越乱,越写越蒙
  2. 对于量上我们可以,每实现了两三个 功能就运行测试看看,是否存在错误,如果存在出现了错误,我们可以在一定的量(范围内),快速的找出哪里出现了问题,从而对它进行调试 ,解决问题,而不是,把项目整体写完了或者是已经实现了好几十个功能,才开始运行测试项目,结果一运行,bug,警告 冒出一大坨,我们先不说,让不让人,抓头发,就是找出问题,恐怕都需要不时间上的浪费吧
  3. 对于代码上的注释,没事多写明白一点,或许有一天,你会感想曾经,那个写了注释的自己或同事
  4. 对于bug 不要害怕,一点一点的调试看看,找出问题的所在,慢慢来,要有耐心,要明白一点现在bug 写的多,以后bug 跟你说拜拜,现在bug ,不解决,bug 天天对你说 明天见

五子棋实现原理解剖

我们使用分布式文件系统,编写该项目

我们这款五子棋游戏是,单机,人与人之间的对战的。角色分为用户1,用户2两位

  • 游戏菜单显示,两种情况,是开始游戏,还是退出游戏
  • 我们定义二维数组 用于五子棋的显示和存放五子棋的信息。显示情况如下:
    • 没有被下过的位置,符号 . 表示
    • 被用户1下过的位置,符号 ● 表示
    • 被用户2下过的位置,符号 ○ 表示
  • 下棋方式是,通过输入坐标的形式,下棋
  • 棋盘结果有四种情况分别是:
    • 棋盘未满,未分胜负,继续下棋
    • 棋盘未满,分胜负,用户1 赢了
    • 棋盘未满,分胜负,用户2 赢了
    • 棋盘已满,未分胜负,平局

功能上简单细节构思

显示打印数组中以 1 开始,显示行号,以及列号

下棋中,所下坐标位置,不可超出棋盘大小,不可下在已经被下过的位置,去重,每下一步,都需要打印棋盘

每下一步棋,都需要判断,下的这一步是否,分出胜负,而不是下了好几步,才判断结果,


定义相关的变量

这里我们的棋盘的行列,用户1, 用户2,以及棋盘的结果的标识 使用 定义,方便修改,以及后期的维护

#define ROW 15    // 棋盘行数
#define COL 15    // 棋盘列数#define PLAYER1 1     // 定义标识用户 1,
#define PLAYER2 2     // 定义标识用户 2// 棋局中的中情况的定义
#define NEXT 0        // 表示没有结果,继续下棋
#define DRAE 3        // 表示棋盘下满了,平局结束

进入游戏的选择

我们把游戏的功能封装写在一个方法中Game() 用于 main 函数调用使用, 使用循环,根据实际情况,我们玩完了一把游戏,可能还会再来一把,所以我们使用循环——> 在循环里头——>再使用分支条件 switch 选择对应的功能, 在循环中定义一个数值,作为循环条件,方便我们更新循环条件,从而达到跳出循环,退出游戏的操作


int main()
{int quit = 0;     // 定义一个标识,用于循环条件的退出int select = 0;   // 对应功能上的选择while (!quit){menc();printf("请输入你的选择: > ");scanf("%d", &select);      // 选择游戏模式switch (select){case 1:Game();     // 进去游戏break;case 0:quit = 1;   // 通过改变循环条件,跳出循环,结束游戏printf("ByeBye!ln\n");break;default:        // 选择错误重新选择printf("Enter Error , Try Again!!! \n");break;}}return 0;
}

打印菜单的功能的实现

void menc()   // 游戏菜单
{printf("#########################\n");printf("### 1.paly     0.Exot ###\n");printf("##### Please Select #####\n");printf("#########################\n");}

游戏函数 Game( ) 的构建

  1. 首先我们需要创建一个二维数组作为棋盘使用,并使用函数 memset 初始化二维数组(棋盘),同时定义一个变量,用于保存棋盘是否继续,如int result = NEXT ,其中的NEXT就是我们定义的标记:未分胜负,棋盘继续的标识
  2. 游戏是只有在分出胜负,才会结束,所以需要让游戏不要中途停止,所以写成循环的方式,进行游戏。
  3. 定义一个函数用于打印棋盘,如:showBoard(board, ROW, COL) 用于打印棋盘,每下一步都需要打印棋盘,传的参数为(数组,数组的行,数组的列)
  4. 接着定义一个下棋的函数用于下棋,如:playerMove(board, ROW, COL, PLAYER1) ,传的参数是(数组,数组的列,数组的行,谁下的(用户标识符号))
  5. 定义一个判断每下一棋,判断是否出胜负的函数如:result = isOver(board, ROW, COL),并返回结果(用户1赢,用户2赢,平局,继续),根据返回结果,如果返回值,不是继续,说明分出结果了,跳出循环,结束游戏,
  6. 退出循环后,再根据返回判断胜负的返回值,判断是谁赢了,还是平局,使用switch(result) 分支语句

逻辑思路

打印棋盘(showBoard( ))——> 用户1下棋(playerMove( ))——>判断胜负结果( isOver( )),(结果上未分胜负)——>打印棋盘(showBoard( ))——>用户2下棋(playerMove( ))——> 判断胜负结果( isOver( )),(结果上未分胜负)——>打印棋盘(showBoard( ))——> 再用户1下棋(playerMove( )),一直这样循环直到分出胜负( isOver( ))


void Game()
{int board[ROW][COL];                 // 使用二维数组,定义棋盘memset(board, 0, sizeof(board));     // 初始化二维数组int result = NEXT;                   // 游戏继续do {showBoard(board, ROW, COL);               // 打印棋盘playerMove(board, ROW, COL, PLAYER1);      // 用户1 下棋result = isOver(board, ROW, COL);      // 判断下了这一手,是否有结果,结果返回if (NEXT != result)   // 根据判断后的返回值,判断是否出了结果,是否还需要继续,NEXT 表示继续{break;}showBoard(board, ROW, COL);               // 打印棋盘playerMove(board, ROW, COL, PLAYER2);      // 用户2 下棋result = isOver(board, ROW, COL);      // 判断下了这一手,是否有结果,结果返回if (NEXT != result)    // 根据判断后的返回值,判断是否出了结果,是否还需要继续, NEXT 表示继续{break;}} while (1);// 跳出循环,根据返回值,判断该局的,结果是,谁赢,谁输,还是平局switch (result){case PLAYER1:showBoard(board, ROW, COL);               // 打印棋盘printf("恭喜用户1,你赢了\n");break;case PLAYER2:showBoard(board, ROW, COL);               // 打印棋盘printf("恭喜用户2,你赢了\n");break;case DRAE:showBoard(board, ROW, COL);               // 打印棋盘printf("平分秋色,平局\n");break;default:           // 不可能会执行到的,这里设置是为了以防万一break;}}

打印棋盘showBoard() 函数

  1. 首先我们需要清屏,每打印一个新的棋盘,清屏一下,这样体验效果更好,注意我们显示的无论是行号还是列好都是从 1 开始的,所以在打印的过程中需要 +1
  2. 首先打印两个空格,为打印棋行号,空出位置,更加美观,再打印列号
  3. 再使用两层循环打印二维数组,显示棋盘,第一层循环打印行号
  4. 两层循环遍历打印二维数组(显示棋盘),同时判断没有下过的位置以符号==.== 显示,用户1:下过的使用● 显示,用户2:下过的使用○ 显示:

// 打印二维数组
void showBoard(const int board[ROW][COL], const int row, const int col)
{//  printf("\e[1;1H\e[2J");  // 清屏system("cls");int i = 0;printf("  ");   // 两个空格for (; i < row; i++)    // 打印行号{printf("%3d", i+1);   // 预留三个位置}printf("\n");for (i = 0; i < row; i++){int j = 0;printf("%2d ",i + 1);  // 预留两个位置for (j; j < col; j++){if (0 == board[i][j])    // 没有下过的位置打印 为 .{printf(" . ");} else if (PLAYER1 == board[i][j]) {  // 用户1 的显示符号●printf("● ");}else                          // 不等于,则是用户2 的显示符号 ○{printf("○ ");                 }}printf("\n");}}

下棋playerMove( )函数

  1. 使用 static 修饰该函数,封装该函数,让函数只能在该文件内使用,提高代码的可维护性
  2. 定义两个全局变量,用于保存,赋值输入的坐标位置,
  3. 判断输入的坐标是否合理:
    • 是否超出棋盘的大小,下的位置是否被人下过。
    • 注意我们输入的坐标是从 1 下标开始的,而数组是从 0 下标开始的,所以在赋值的过程中需要 -1
  4. 写成循环,因为有可能输入的坐标不合理,需要重新输入,合理时,赋值坐标到数组中,并退出循环,注意赋值到数组中的值,是该用户所下的,标识数值。在宏中就定义好的
  5. #define PLAYER1 1 // 定义标识用户 1
    #define PLAYER2 2 // 定义标识用户 2
// 下棋
static void playerMove(int board[ROW][COL], const int row, const int col, const int who)
{while (1){printf("player[%d] pleach Enter Your Pos#> ", who);  // 提示打印用户谁的输入scanf("%d %d", &x, &y);       // 输入坐标// 输入的坐标超出了棋盘,不合法,重新输入if (x < 1 || x > row || y < 1 || y > col){printf("超过棋盘了,请重新输入\n");continue;    // 跳过本次循环,重新输入}// 输入的坐标位置,已经被占用了,不合法,重新输入if (0 != board[x-1][y-1])     {printf("pos IsOccupied!\n");continue;   // 跳过本次循环,重新输入}// 运行到这,说明该坐标没有问题,可以下入到棋盘中去了board[x - 1][y - 1] = who;break;    // 跳出循环}}

判断胜负isOver( )函数

  1. 使用 static 修饰该函数,封装该函数,让函数只能在该文件内使用,提高代码的可维护性

  2. 定义一个枚举结构用于表示各个方位的数值的标识,如typedef enum Dir

  3. 定义一个函数chessCount(board, row, col, LEFT) ,用于计算二维数组中各个方位的上相同的连续出现的数值,返回计算得到的数值,因为在该函数中并没有计算到包含到,本身所下的个数,所以需要额外加上 +1

  4. 判断返回的连续出现的数值,是否存在 >=5 的个数,有则存在,五子连珠的情况说明有人赢了,再根据所走这步的,用户是谁,判断是谁,赢了

  5. 如果没有五子连珠,则再循环遍历二位数组,是否全部下完了,但凡存在没下的,下完了,则表示棋盘未满,未分出胜负,返回继续下棋,返回值为return NEXT

  6. 以上4,5这两种情况都没有出现的话,棋盘满了,未分出胜负,平局,返回值为 return DRAE

枚举类型:表示方位

typedef enum Dir  // 枚举 坐标上的方向,注意,枚举以逗号分割开来
{LEFT,       // 左边RIGHT,      // 右边UP,         // 上边DOWN,       // 下边LEFT_UP,    // 左上边LEFT_DOWN,  // 左下边RIGHT_UP,   // 右上边RIGHT_DOWN  // 右下边// 注意 枚举中的最后一个属性,不要加逗号分隔开,不然会报错的
}Dir;
// 走一步,判断结果
static int isOver(const int board[ROW][COL], const int row, const int col)
{// 从四个位置上判断,可能五子连珠的,可能性,当连续的相同的字符,数量个数为 5 时,表示有一方赢了// 在此基础上都需要加上 1 ,因为本身的位置上的,没有包含计算上,是需要计算上的// 左右横方向上的个数int count1 = chessCount(board, row, col, LEFT) + chessCount(board, row, col, RIGHT) + 1;// 上下纵方向上的个数int count2 = chessCount(board, row, col, UP) + chessCount(board, row, col, DOWN) + 1;// 左斜上方向上的个数int count3 = chessCount(board, row, col, LEFT_DOWN) + chessCount(board, row, col, RIGHT_UP) + 1;// 右斜下方向上的个数int count4 = chessCount(board, row, col, LEFT_UP) + chessCount(board, row, col, RIGHT_DOWN) + 1;// 只要在任意位置上,个数上 >= 5 就,实现了五子连珠,就有获胜了if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5){if (board[x - 1][y - 1] == PLAYER1){return PLAYER1;   // 表示用户1 赢了}else{return PLAYER2;   //否则就是 表示用户2 赢了}}// 循环遍历二维数组(棋盘),判断棋盘是否存在满了,如果有一个棋位置,还可以下,就表示还可以继续下棋,for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (board[i][j] == 0){return NEXT;   // 继续,棋盘没有满}}}return DRAE;        // 走到这表示棋盘满了,平局}

计算坐标周围连续的个数chessCount( )函数


根据所下的位置判断,是否存在五子连珠 的情况:一共存在四种情况分别是

  • 横方向上的 五子连珠

  • 纵方向上的五子连珠

  • 左斜向下的五子连珠

  • 右斜上的五子连珠


注意 :编程中的图形界面上的坐标是与,数学上的坐标是相反的,数学上的,横为 X轴,纵为 Y轴 ,而编程中的是横为 Y轴,纵为 X 轴 ,如下图所示:

根据所传参数中的方位,定义多条分支选择switch() ,作出相应的坐标上的移动,我们需要保留原来的坐标位置用于判断,所以我们需要拷贝复制一份,坐标用于移动,防止丢失原来的坐标位置,因为我们需要计算的是连续的,所以需要写在循环中,

方位上的移动坐标

左边 :y–;

右边:y++;

上边:x++;

下边:x–;

左下边:y–;x–;

左上边:x++;y–;

右上边:y++;x++;

右下边:y++;x–;


  1. 每移动一个坐标位置,都需要判断该坐标是否,越界了,是否超出了棋盘的范围,超出了,不用计算了,跳出循环
  2. 在确定移动坐标合理时,再判断该移动的坐标位置上的数值,是否与你所下的位置上的坐标上的数值相等,相等说明连续,计数,不相等,说明不连续,不计数,退出循环
  3. 退出循环后,返回所计数的结果
  4. 最后,因为该函数计数时,是没有计算到,包含到,所下位置的本身个数,所以需要额外 + 1

// 计算下的点位置上的,4个方向上的连续字符的 个数,
// 注意编程上的图形界面的坐标是,与数学上的坐标 x,y 是相反的,横坐标为 y, 纵坐标为 x 的
int chessCount(const int board[ROW][COL], const int row, const int col, Dir d)
{int count = 0;int _x = x-1;int _y = y-1;   // 拷贝一份坐标,用于移动,防止改变原来的,坐标,// 注意是在数组上的实际坐标,不是你输入的,数组从零开始while (1){switch (d){case LEFT:        // 左边_y--;break;case UP:          // 上边_x++;break;case DOWN:        // 下边_x--;break;case LEFT_DOWN:   // 左下_x--;_y--;break;case LEFT_UP:     // 左上_x++;_y--;break;case RIGHT:       // 右边_y++;break;case RIGHT_DOWN:  // 右下_x--;_y++;break;case RIGHT_UP:    // 右上_x++;_y++;break;default:break;}// 坐标越界了,跳出循环if (_x < 0 || _x > row - 1 || _y < 0 || -y > col - 1){break;}//if (board[_x][_y] != board[x - 1][y - 1])//{// break;      // 表示数组上的数值也就是棋盘上的点,不连续了,不用加加了,跳出循环//}if (board[_x][_y] == board[x - 1][y - 1]){count++;     // 说明数组上的数值也就是棋盘上的点,连续,加加计数} else  // 否则表示不相等,不连续,跳出循环{break; // 表示数组上的数值也就是棋盘上的点,不连续了,不用加加了,跳出循环}}return count;    // 跳出循环,返回在连续的个数
}

所有功能都实现了,可以运行该项目程序了,判断是否存在错误


五子棋完整代码实现

这里采用了分布式文件系统,其中的代码大家只需要,根据对应的文件,复制粘贴内容,就可以了,使用 VS 运行了,注意:不要缺失了,不然,可能无法运行的

game.h

用于存放 :头文件的引入,宏定义,变量,函数的声明,结构体,枚举

#pragma once
#define  _CRT_SECURE_NO_WARNINGS  1#include<stdio.h>
#include<string.h>
#include<stdlib.h>#define ROW 15    // 棋盘行数
#define COL 15    // 棋盘列数#define PLAYER1 1     // 定义标识用户 1,
#define PLAYER2 2     // 定义标识用户 2// 棋局中的中情况的定义
#define NEXT 0        // 表示没有结果,继续下棋
#define DRAE 3        // 表示棋盘下满了,平局结束typedef enum Dir  // 枚举 坐标上的方向,注意,枚举以逗号分割开来
{LEFT,       // 左边RIGHT,      // 右边UP,         // 上边DOWN,       // 下边LEFT_UP,    // 左上边LEFT_DOWN,  // 左下边RIGHT_UP,   // 右上边RIGHT_DOWN  // 右下边// 注意 枚举中的最后一个属性,不要加逗号分隔开,不然会报错的
}Dir;extern void menc();      // 打印游戏菜单
extern void Game();      // 进入游戏
extern void playerMove(int board[ROW][COL], const int row, const int col, const int who);    // 下棋
extern int isOver(const int board[ROW][COL], const int row, const int col);        // 判断下一步后的,结果
extern int chessCount(const int board[ROW][COL], const int row, const int col, Dir d);     // 计算,连续出现相同的个数,从而判断是否有五子连珠
extern void showBoard(const int board[ROW][COL], const int row, const int col);    // 打印二维数组,棋盘

game.c

存放五子棋中对应功能实现的函数

#include "game.h"int x = 0;   // 定义全局变量,X 坐标
int y = 0;   // 定义全局变量,y 坐标void menc()   // 游戏菜单
{printf("#########################\n");printf("### 1.paly     0.Exot ###\n");printf("##### Please Select #####\n");printf("#########################\n");}void Game()
{int board[ROW][COL];                 // 使用二维数组,定义棋盘memset(board, 0, sizeof(board));     // 初始化二维数组int result = NEXT;                   // 游戏继续do {showBoard(board, ROW, COL);               // 打印棋盘playerMove(board, ROW, COL, PLAYER1);      // 用户1 下棋result = isOver(board, ROW, COL);      // 判断下了这一手,是否有结果,结果返回if (NEXT != result)   // 根据判断后的返回值,判断是否出了结果,是否还需要继续,NEXT 表示继续{break;}showBoard(board, ROW, COL);               // 打印棋盘playerMove(board, ROW, COL, PLAYER2);      // 用户2 下棋result = isOver(board, ROW, COL);      // 判断下了这一手,是否有结果,结果返回if (NEXT != result)    // 根据判断后的返回值,判断是否出了结果,是否还需要继续, NEXT 表示继续{break;}} while (1);// 跳出循环,根据返回值,判断该局的,结果是,谁赢,谁输,还是平局switch (result){case PLAYER1:showBoard(board, ROW, COL);               // 打印棋盘printf("恭喜用户1,你赢了\n");break;case PLAYER2:showBoard(board, ROW, COL);               // 打印棋盘printf("恭喜用户2,你赢了\n");break;case DRAE:showBoard(board, ROW, COL);               // 打印棋盘printf("平分秋色,平局\n");break;default:           // 不可能会执行到的,这里设置是为了以防万一break;}}// 下棋
static void playerMove(int board[ROW][COL], const int row, const int col, const int who)
{while (1){printf("player[%d] pleach Enter Your Pos#> ", who);  // 提示打印用户谁的输入scanf("%d %d", &x, &y);       // 输入坐标// 输入的坐标超出了棋盘,不合法,重新输入if (x < 1 || x > row || y < 1 || y > col){printf("超过棋盘了,请重新输入\n");continue;    // 跳过本次循环,重新输入}// 输入的坐标位置,已经被占用了,不合法,重新输入if (0 != board[x-1][y-1])     {printf("pos IsOccupied!\n");continue;   // 跳过本次循环,重新输入}// 运行到这,说明该坐标没有问题,可以下入到棋盘中去了board[x - 1][y - 1] = who;break;    // 跳出循环}}// 走一步,判断结果
static int isOver(const int board[ROW][COL], const int row, const int col)
{// 从四个位置上判断,可能五子连珠的,可能性,当连续的相同的字符,数量个数为 5 时,表示有一方赢了// 在此基础上都需要加上 1 ,因为本身的位置上的,没有包含计算上,是需要计算上的// 左右横方向上的个数int count1 = chessCount(board, row, col, LEFT) + chessCount(board, row, col, RIGHT) + 1;// 上下纵方向上的个数int count2 = chessCount(board, row, col, UP) + chessCount(board, row, col, DOWN) + 1;// 左斜上方向上的个数int count3 = chessCount(board, row, col, LEFT_DOWN) + chessCount(board, row, col, RIGHT_UP) + 1;// 右斜下方向上的个数int count4 = chessCount(board, row, col, LEFT_UP) + chessCount(board, row, col, RIGHT_DOWN) + 1;// 只要在任意位置上,个数上 >= 5 就,实现了五子连珠,就有获胜了if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5){if (board[x - 1][y - 1] == PLAYER1){return PLAYER1;   // 表示用户1 赢了}else{return PLAYER2;   //否则就是 表示用户2 赢了}}// 循环遍历二维数组(棋盘),判断棋盘是否存在满了,如果有一个棋位置,还可以下,就表示还可以继续下棋,for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (board[i][j] == 0){return NEXT;   // 继续,棋盘没有满}}}return DRAE;        // 走到这表示棋盘满了,平局}// 计算下的点位置上的,4个方向上的连续字符的 个数,
// 注意编程上的图形界面的坐标是,与数学上的坐标 x,y 是相反的,横坐标为 y, 纵坐标为 x 的
int chessCount(const int board[ROW][COL], const int row, const int col, Dir d)
{int count = 0;int _x = x-1;int _y = y-1;   // 拷贝一份坐标,用于移动,防止改变原来的,坐标,// 注意是在数组上的实际坐标,不是你输入的,数组从零开始while (1){switch (d){case LEFT:        // 左边_y--;break;case UP:          // 上边_x++;break;case DOWN:        // 下边_x--;break;case LEFT_DOWN:   // 左下_x--;_y--;break;case LEFT_UP:     // 左上_x++;_y--;break;case RIGHT:       // 右边_y++;break;case RIGHT_DOWN:  // 右下_x--;_y++;break;case RIGHT_UP:    // 右上_x++;_y++;break;default:break;}// 坐标越界了,跳出循环if (_x < 0 || _x > row - 1 || _y < 0 || -y > col - 1){break;}//if (board[_x][_y] != board[x - 1][y - 1])//{// break;      // 表示数组上的数值也就是棋盘上的点,不连续了,不用加加了,跳出循环//}if (board[_x][_y] == board[x - 1][y - 1]){count++;     // 说明数组上的数值也就是棋盘上的点,连续,加加计数} else  // 否则表示不相等,不连续,跳出循环{break; // 表示数组上的数值也就是棋盘上的点,不连续了,不用加加了,跳出循环}}return count;    // 跳出循环,返回在连续的个数
}// 打印二维数组
void showBoard(const int board[ROW][COL], const int row, const int col)
{//  printf("\e[1;1H\e[2J");  // 清屏system("cls");int i = 0;printf("  ");   // 两个空格for (; i < row; i++)    // 打印行号{printf("%3d", i+1);   // 预留三个位置}printf("\n");for (i = 0; i < row; i++){int j = 0;printf("%2d ",i + 1);  // 预留两个位置for (j; j < col; j++){if (0 == board[i][j])    // 没有下过的位置打印 为 .{printf(" . ");} else if (PLAYER1 == board[i][j]) {  // 用户1 的显示符号●printf("● ");}else                          // 不等于,则是用户2 的显示符号 ○{printf("○ ");                 }}printf("\n");}}

test.c

main 函数的所在文件,用于测试五子棋,是否存在错误,因为有关代码封装的比较好,所以在该main 函数中代码量并不多。

// #define  _CRT_SECURE_NO_WARNINGS  1#include"game.h"int main()
{int quit = 0;     // 定义一个标识,用于循环条件的退出int select = 0;   // 对应功能上的选择while (!quit){menc();printf("请输入你的选择: > ");scanf("%d", &select);      // 选择游戏模式switch (select){case 1:Game();     // 进去游戏break;case 0:quit = 1;   // 通过改变循环条件,跳出循环,结束游戏printf("ByeBye!ln\n");break;default:        // 选择错误重新选择printf("Enter Error , Try Again!!! \n");break;}}return 0;
}

这便是五子棋实现的所有代码,运行看看


最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见!

人与人之间的单机五子棋 —— C语言实现相关推荐

  1. 人与动物之间有没有一条不可逾越的鸿沟?——从基础存在论到生命哲学

    来源:<哲学动态> 2018年第12期作者:舒红跃(湖北大学哲学学院)张哲(湖北省道德与文明研究中心) 海德格尔<存在与时间>中对"此在"的生存论刻画是哲学 ...

  2. 人与人之间关系的随想

    注意:本文包含若干软件开发术语. 写之前,刚好有个朋友提醒我,老外不这样.所以,我这里所写的,仅限我对中国大陆地区(特别是北方)人与人之间关系的一些不成熟的想法. 人和人之间相处,经常会产生各种问题. ...

  3. 人之间的尊重是相互的_人与人之间的感情,最基本的是相互尊重

    有很多人就是靠一些冒犯别人的办法来刷自己的存在感,但很多时候,这样的人刷着刷着就把自己刷没了.有的感情,自己很看重,别人却不当回事:人与人之间的感情,最基本的是相互尊重. 有的感情,自己很看重,别人却 ...

  4. 人与人之间交往最重要的是什么?

    真诚,就是待人真心实意. 真诚,就是对人说真话,吐真情,对人满腔热情,真心实意,毫无矫揉造作,毫无虚情假意. 真诚,就是与人交往中相信人,信任人,对人满怀信心,坦坦荡荡,不疑神疑鬼,不遮遮掩掩. 真诚 ...

  5. 人之间的尊重是相互的_人与人之间,尊重很重要

    问题:怎样才能每天免费收到这种文章呢?  答案:只需要点击上方蓝字<鸡汤心语>关注即可! 人与人之间,尊重是相互的 心与心相交,尊重是必须的 尊重,是一个人教养 体现在做人做事 尊重,是一 ...

  6. 人之间的尊重是相互的_人与人之间要学会相互尊重

    偶然间想说说人与人之间相互尊重的话题,因为,在当今社会中,真有那么一大部分人不懂得如何去尊重别人或不懂得相互尊重,在人与人之间相处的范围中产生了一定的影响.所以,仅就人与人之间是否需要尊重说说个人的态 ...

  7. 思维方式-《终身成长》书中的精髓:决定人与人之间巨大差距的,是你的思维模式。

    <终身成长>书中的精髓:决定人与人之间巨大差距的,是你的思维模式. 有些朋友可能觉得智商.情商和财富才是人与人之间差距所在,不过别急,请听我讲一个故事. 大家都知道迈克尔·乔丹,他是有史以 ...

  8. 神州优车粗暴裁员:人与人之间最起码的尊重呢?

    年底了,又有一些企业开始想着怎么"优化"人员结构还不用"安抚"员工了. 这是一段神州优车 HR 小姐姐与试用期即将满 6 个月的员工.在工位上展开的一段对话视频 ...

  9. 人之间的尊重是相互的_人与人之间彼此尊重是相互的,你若敬我一尺,我必敬你一丈...

    01 静坐常思己过,闲谈莫论人非,当你不开心的时候,想想自己还剩下多少天可以折腾,还有多少时间够你作践.你开心,这一天过了:不开心,一天也过了.想明白了,你就再也不会生气了. 02 当你烦恼的时候,想 ...

最新文章

  1. 《VMware Virtual SAN权威指南》一2.2 VSAN的要求
  2. java hashmapconcurrentHashmap源理
  3. boost::edge_coloring用法的测试程序
  4. sql 2008 使用output避免数据修改后的二次查询
  5. django模型查询_如何在Django中编写有效的视图,模型和查询
  6. 数据结构与算法之七归并排序
  7. javaWeb:相关监听方法汇总
  8. mybatis 实现查询商品列表的分页
  9. 视频教程-SQL语句视频课程(进阶版)-Oracle
  10. 使用OpenGL绘制shp文件
  11. PhotoShop简单案例(4)——利用ps制作正在加载中动画(loading.gif)
  12. 微软和美国航空航天局(NASA)强强联手,推出Python免费课程
  13. 国内及国际公共DNS收录
  14. 立创开源 | 基于555定时器的电子琴设计
  15. Windows上搭建PHP开发环境
  16. 敏捷迭代管理 --需求变更规范
  17. 一只小白,在学习delphi.感觉很吃力。。
  18. 图像数据增强及其对应的标签扩充
  19. 安卓 网络工具_小米公布MIUI适配计划,支持10台机型升级安卓Q,9款今年内测
  20. IP地址分类及子网掩码划分网段详解!!!

热门文章

  1. android fun os,vivo也要吃上奥利奥!FuntouchOS宣布Android Oreo机型适配列表
  2. 王者荣耀s20赛季服务器维护,王者荣耀s20赛季开启时间 王者荣耀s20赛季段位继承规则及赛季皮肤...
  3. 谈谈浏览器的缓存过期时间
  4. 什么是electron?
  5. 四川数字经济发展分析:四川21市州数字经济发展活跃度解密
  6. Unity中左手坐标系的四元数转右手坐标系中的四元数
  7. duo是什么意思_吃鸡上面duo是什么意思 | 手游网游页游攻略大全
  8. HashMap 分析
  9. java swarm有什么用,Docker Swarm的使用总结
  10. 阴阳师哪些服务器可以跨系统转移,《阴阳师》跨系统角色转移攻略