思想
1、棋盘大小是3*3的,所以需要一个二维数组,需要将二维数组的初始为“空格”。
2、有了内容就可以打印了,之后先让玩家开始下棋,接着电脑下棋。
3、无论是玩家下棋,还是电脑下棋,都会出现一方胜出,或平局(电脑赢、玩家赢、平局、继续下棋),进行判断(赢得方式:任意一行连成三子、任意一列连成三子或者对角线连成三子)
实现
测试:菜单打印
为了方便创建两个.c文件一个是game.c 一个是test.c 和一个.h文件 game.h
menu函数实现一个简易的菜单
这里的头文件全都引在game.h中
程序分析
开始程序:先打印菜单也就是调用 menu 函数,之后输入 1开始游戏、输入 0退出游戏、输入非法值提示。当输入 0时,while循环正好结束,当输入非 0值循环继续符合 while 循环
初始化棋盘和打印棋盘
这里为了可以改变行和列,将它们的值定义在game.h里了 现在的值都为 3
//初始化棋盘
void InitBorad(char borad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
borad[i][j] = '*';
}
}
}
//显示棋盘
void Displayborad(char borad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", borad[i][j]);
}
printf("\n");
}
}
程序分析
InisBorad 函数完成初始化数组的内容,根据分析一个初始化为“空格”(不宜观察),现在初始化为' # '是为了方便观察,将数组元素遍历进行赋值;在遍历打印
此时打印的结果为:
这样打印如果是“空格”的话,什么都看不到,不容易落子,所以应该优化一下,打印分割行便于落子
如果可以把棋盘打印成这样就挺好的
如图画质被压缩 私信我
这里可以先打印图 a 而图 b的打印次数比图 a要少1次
void Displayborad(char borad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < col; i++)
{
printf(" %c | %c | %c ", borad[i][0], borad[i][1], borad[i][2]);
printf("\n");
if (i < col - 1)
{
printf("---|---|---");
printf("\n");
}
}
}
此时打印结果为:
虽然是打印出来了,但这太局限了,所以这样分析不对,应该再拆
如果画质被压缩 私信我
现在将图 a 和图 b再拆成为 图 a 1 和图 b 1
同样图 a 1比图 b 1 需要多打印一次
而图 a 1 中的 a 图比 b 图要多打印一次
而图 b 1 中的 a 图比 b 图要多打印一次
void Displayborad(char borad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", borad[i][j]);
if (j < col - 1)
{
printf("|");//比上面打印的少一次
}
}
printf("\n");
if (i < row - 1)//下面整体比上面整体少一次打印
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");//比上面打印少一次
}
}
}
printf("\n");
}
}
此时打印结果为:
开始下棋
玩家下棋
这里规定玩家的棋子为 *
电脑的棋子为 #
程序分析
既然是玩家 有可能不是程序员,所以下标应该从1开始而不是0
再判断玩家输入的坐标是合法,如果合法,要判断该坐标是否被占用,一切都满足方可落子
void PlayMove(char borad[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋\n");
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (borad[x - 1][y - 1] == ' ')//判断该位置是否没落子
{
borad[x - 1][y - 1] = '*';//将 * 赋给坐标
break;
}
else
{
printf("该坐标已被占用,请重新输入\n");
}
}
else
{
printf("该坐标非法,请重新输入\n");
}
}
}
测试结果:
符合逻辑
电脑下棋(用随机值完成下棋 所以电脑下的棋是随机的)
后续会更新较强的电脑
void ComputerMove(char borad[ROW][COL], int row, int col)
{
while (1)
{
int x = rand() % row;//rand生成的随机值模row得到的值为0到row左闭右开的区间
int y = rand() % col;//同理
if (x >= 0 && x < row && y >= 0 && y < col)//判断坐标的范围是否合法
{
if (borad[x][y] == ' ')//判断坐标是否未落子
{
borad[x][y] = '#';
break;
}
}
}
}
程序分析
rand函数获得随机值模 row 得到的值在 0 到 row 的左闭右开的区间
之后像判断玩家一样判断 x ,y 的坐标,但是不用提示
判断输赢
思想中提到判断输赢,有四种状态分别是 1、玩家胜出 2、电脑胜出 3、平局 4、继续下棋 那么判断输赢有三种情况分别是 1、任意一行三子相同 2、任意一列三子相同 3、对角线三子相同 这里要注意判断棋子是否相等的时候如果全是“空格”不算
//玩家赢 *
//电脑赢 #
//平局 Q
//继续 C
IsFull(char borad[ROW][COL], int row, int col);
char IsWin(char borad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
//判断任意一行,是否有相等的棋子
for (i = 0; i < row; i++)
{
if (borad[i][0] == borad[i][1] && borad[i][1] == borad[i][2] && borad[i][0] != ' ')
{
return borad[i][0];
}
}
//判断任意一列,是否有相等的棋子
for (j = 0; j < col; j++)
{
if (borad[0][j] == borad[1][j] && borad[1][j] == borad[2][j] && borad[0][j] != ' ')
{
return borad[0][j];
}
}
//判断对角线是否有相等的棋子
if (borad[0][0] == borad[1][1] && borad[1][1] == borad[2][2] && borad[1][1] != ' ')
{
return borad[0][0];
}
if (borad[0][2] == borad[1][1] && borad[1][1] == borad[2][0] && borad[0][2] != ' ')
{
return borad[0][2];
}
//判断平局,如果平局,就代表棋盘满了
IsFull(borad, row, col);
}
IsFull(char borad[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 (borad[i][j] == ' ')//如果有空格,就说明了棋盘没有满所以继续
return 'C';
}
}
return 'Q';
}
程序分析
为什么判断玩家或电脑的输赢要用 * 和 # 呢?
因为可以直接 return 不用再判断 只需要少量的代码即可完成
if (tmp == '*')
printf("玩家赢\n");
else if (tmp == '#')
printf("电脑赢\n");
else
printf("平局\n");
game.h的代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
//初始化棋盘
void InitBorad(char borad[ROW][COL], int row, int col);
//显示棋盘
void Displayborad(char borad[ROW][COL], int row, int col);
//玩家下棋
void PlayMove(char borad[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char borad[ROW][COL], int row, int col);
//判断输赢
char IsWin(char borad[ROW][COL], int row, int col);
game.c的代码
#include"game.h"
//初始化棋盘
void InitBorad(char borad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
borad[i][j] = ' ';
}
}
}
//显示棋盘
// 不易落子
//void Displayborad(char borad[ROW][COL], int row, int col)
//{
// int i = 0;
// int j = 0;
// for (i = 0; i < row; i++)
// {
// for (j = 0; j < col; j++)
// {
// printf(" %c ", borad[i][j]);
// }
// printf("\n");
// }
//}
//void Displayborad(char borad[ROW][COL], int row, int col)
//{
// int i = 0;
// int j = 0;
// for (i = 0; i < col; i++)
// {
// printf(" %c | %c | %c ", borad[i][0], borad[i][1], borad[i][2]);
// printf("\n");
// if (i < col - 1)
// {
// printf("---|---|---");
// printf("\n");
// }
// }
//}
void Displayborad(char borad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", borad[i][j]);
if (j < col - 1)
{
printf("|");//比上面打印的少一次
}
}
printf("\n");
if (i < row - 1)//下面整体比上面整体少一次打印
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");//比上面打印少一次
}
}
}
printf("\n");
}
}
void PlayMove(char borad[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋\n");
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (borad[x - 1][y - 1] == ' ')//判断该位置是否没落子
{
borad[x - 1][y - 1] = '*';//将 * 赋给坐标
break;
}
else
{
printf("该坐标已被占用,请重新输入\n");
}
}
else
{
printf("该坐标非法,请重新输入\n");
}
}
}
void ComputerMove(char borad[ROW][COL], int row, int col)
{
while (1)
{
int x = rand() % row;//rand生成的随机值模row得到的值为0到row左闭右开的区间
int y = rand() % col;//同理
if (x >= 0 && x < row && y >= 0 && y < col)//判断坐标的范围是否合法
{
if (borad[x][y] == ' ')//判断坐标是否未落子
{
borad[x][y] = '#';
break;
}
}
}
}
//玩家赢 *
//电脑赢 #
//平局 Q
//继续 C
IsFull(char borad[ROW][COL], int row, int col);
char IsWin(char borad[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
//判断任意一行,是否有相等的棋子
for (i = 0; i < row; i++)
{
if (borad[i][0] == borad[i][1] && borad[i][1] == borad[i][2] && borad[i][0] != ' ')
{
return borad[i][0];
}
}
//判断任意一列,是否有相等的棋子
for (j = 0; j < col; j++)
{
if (borad[0][j] == borad[1][j] && borad[1][j] == borad[2][j] && borad[0][j] != ' ')
{
return borad[0][j];
}
}
//判断对角线是否有相等的棋子
if (borad[0][0] == borad[1][1] && borad[1][1] == borad[2][2] && borad[1][1] != ' ')
{
return borad[0][0];
}
if (borad[0][2] == borad[1][1] && borad[1][1] == borad[2][0] && borad[0][2] != ' ')
{
return borad[0][2];
}
//判断平局,如果平局,就代表棋盘满了
IsFull(borad, row, col);
}
IsFull(char borad[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 (borad[i][j] == ' ')//如果有空格,就说明了棋盘没有满所以继续
return 'C';
}
}
return 'Q';
}
test.c的代码
#include"game.h"
void menu()
{
printf("************************\n");
printf("****** 1. play ******\n");
printf("****** 2, exit ******\n");
printf("************************\n");
}
void game()
{
char tmp = 0;
int borad[ROW][COL] = { 0 };
InitBorad(borad, ROW, COL);//初始化棋盘
Displayborad(borad, ROW, COL);//显示棋盘
//显示完之后死循环下棋,直到分出胜负或者棋盘满了
while (1)
{
PlayMove(borad, ROW, COL);//玩家下棋
tmp = IsWin(borad, ROW, COL);
if (tmp != 'C')
break;
Displayborad(borad, ROW, COL);//显示棋盘
ComputerMove(borad, ROW, COL);//电脑下棋
tmp = IsWin(borad, ROW, COL);
if (tmp != 'C')
break;
Displayborad(borad, ROW, COL);//显示棋盘
}
if (tmp == '*')
printf("玩家赢\n");
else if (tmp == '#')
printf("电脑赢\n");
else
printf("平局\n");
}
int main()
{
int input = 0;
do {
srand((unsigned)time(NULL));
menu();//打印菜单
scanf("%d", &input);
switch (input)
{
case 1:game();
break;
case 0:printf("退出游戏\n");
break;
default:printf("输入错误\t请输入 1或 2\n");
break;
}
} while (input);
return 0;
}
到这里除了电脑下棋水平不行,就完成了三子棋小游戏了
后续会更新较强的.................
persistence