游戏介绍:一张棋盘,玩家和电脑前后落子,谁先连着3课棋子谁获得胜利。
准备阶段思路:准备一个棋盘,用 * 代表玩家棋子,用 # 代表电脑棋子,用空格表示未落子棋子
5.判断胜负和平局
游戏目录
void menu()
{
printf("***** 1. paly *****\n");
printf("***** 0. exit *****\n");
}
选择1进入游戏
int main()
{
int input = 0;
do
{
printf("请选择:\n");
menu();
scanf("%d", &input);
switch (input)
{
case 1:
game();//进入游戏
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("请重新选择\n");
break;
}
} while (input);
return 0;
}
初始化棋子(数组)和棋盘
char aboad[ROW][COL] = { 0 };//定义棋子(数组)
Initaboad(aboad, ROW, COL);//初始化棋子
Initchess(aboad, ROW, COL);//打印棋盘,这个函数需要反复调用,因为电脑和玩家每次落子后都需要打印一次
其中ROW和COL定义:
#define ROW 3
#define COL 3
棋子打印成空格即可,其实也可以打印为其他字符,但是空格视觉效果最好
void Initaboad(char aboad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
aboad[i][j] = ' ';
}
}
}
然后初始化棋盘。这个需要多写和画图,初始化棋盘用了很多时间
分析初始化的每一步
这是棋盘的样子
void Initchess(char aboad[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", aboad[i][j]);//aboad[i][j]这元素在上一个调用函数中被初始化为空格
//现在printf函数里面就是输出的三个空格,i和j循环了三次,但是打印的 | 和 --- 只打印了两次
//其中---对应的就是三个空格的位置,我们打印的棋子在中间那个空格
if (j < col - 1)
{
printf("|");
}//所以减少一次,在最后一列的时候取消掉 |
}
printf("\n");
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if(j<col-1)
printf("|");
}
printf("\n");
}
}
}
其中修改ROW和COL的值就可以改变棋盘大小
然后玩家落子:
落子逻辑:先判断空白,按照玩家的逻辑,九宫格是从1.1到3.3,而我们数组的范围是0.0到2.2,所以写代码的时候需要-1. 还有就是如果超乎范围需要提醒玩家然后重新落子,如果输入的格子是下过的话也需要提醒重新落子
Playeraboad(aboad, ROW, COL);//开始下棋这是玩家开始下
Initchess(aboad, ROW, COL);//下了就打印一次
//玩家下棋
void Playeraboad(char aboad[ROW][COL], int row, int col)
{
printf("请玩家选择下棋坐标:\n");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
while (1)
{
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (aboad[x - 1][y - 1] == ' ')
{
aboad[x - 1][y - 1] = '*';
break;
}
else
{
printf("该格子已经被占用,请重新输入\n");
Playeraboad(aboad, ROW, COL);//注意此时需要重新调用该函数,不然会跳过玩家
//这个落子机会
break;
}
}
else
{
printf("坐标非法,请重新输入\n");
Playeraboad(aboad, ROW, COL);//同上需要重新调用,一直到坐标合理为止
break;
}
}
}
然后是电脑落子:电脑比较简单是随机落子,只需要写一个随机函数
头文件:
#include <stdlib.h>
#include <time.h>
srand((unsigned int)time(NULL));
电脑落子
//电脑开始
//电脑只需要判断是否为空格即可
void Computeraboad(char aboad[ROW][COL], int row, int col)
{
printf("电脑开始落子:\n");
int x = 0;
int y = 0;
//电脑是随机值
while (1)
{
x = rand() % row;//x的范围是0到2 注意:不要减1
y = rand() % col;
if (aboad[x][y] == ' ')
{
aboad[x][y] = '#';
break;
}
else
;
}
}
注意:在每一次落子后都要打印一次
然后是判断胜负和是否下满,判断胜负可以在电脑落子过后,但是判断下满必须是在玩家落子之后,电脑落子之前。因为是玩家先手,有可能玩家落子后刚好下满,然后电脑是判断有无空格,一直没空格,电脑就会一直卡住。
在这里我把胜负和下满这两种结果合二为一。所以放在了玩家落子和电脑落子之间
//构造一个函数,根据返回值判断胜负和平局
char winer = WinPlayer(aboad, ROW, COL);
if (winer == '*')
{
printf("玩家获胜\n");
break;
}
if (winer == '#')
{
printf("电脑获胜\n");
break;
}
if (winer == 'Q')
{
printf("平局\n");
break;
}
if (winer == 'G')
printf("go on\n");
我构造的是判断胜负的函数,在判断胜负里面调用了判断下满(平局)的函数
//判断平局
int Iffull(char aboad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (aboad[i][j] == ' ')
return 0;
}
}
return 1;//返回1表示已经没有空格了
}
//评出胜方
char WinPlayer(char aboad[ROW][COL], int row, int col)
{
//胜利方式有横3 竖3 斜3 3中方式
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
if (aboad[i][0] == aboad[i][1] && aboad[i][1] == aboad[i][2])
return aboad[i][0];
}
for (j = 0; j < col; j++)
{
if (aboad[1][j] == aboad[2][j] && aboad[2][j] == aboad[0][j])
return aboad[1][j];
}
if (aboad[1][1] == aboad[2][2] && aboad[1][1] == aboad[0][0])
return aboad[0][0];
if (aboad[0][2] == aboad[1][1] && aboad[1][1] == aboad[2][0])
return aboad[0][0];
//return 返回是的符号如:* #..
int sz = Iffull(aboad, ROW, COL);//调用平局函数
if (sz == 1)
return 'Q';//返回Q代表平局
return 'G';
}
但是上面代码有个弊端,就是不能通过修改ROW和COL的值来更改胜负规则,比如是8*8的棋盘,那么胜利方式只会产生在3*3棋盘的地方。
总结:构造棋盘和判断平局的需要多动动脑子,多写几次就好了。其中的电脑只会随机落子,没有难度。还有就是没有电脑先手落子的情况。,关于让电脑落子变得更灵活,这个有点复杂,我目前只能想到暴力求解一种方法。就是把所有结果都写出来然后一一判断。但是那样效率太低而且太耗时间。等我有时间后在修改一下判断胜负和电脑落子难度,暂时就这样