目录
1.1游戏的运行逻辑
三子棋:规则运行规则很简单,就像平常玩的(井字棋)的规则不能说完全一样,简直就是一模一样。只要是棋盘上的三个棋子连成一列就算获胜,不管是横列,数列抑或斜列只要是连成一列就算获胜。
1.2 代码实行的逻辑
1.2.1 代码分模块
首先,为什么要代码分模块呢?
从初学者的角度来说,这个虽说是个小游戏,但是总代码量也超出了200行,从实
际的角度讲,分模块写不仅可以讲各个函数独立化是主函数的代码量变少,对于初学者
来讲更有条理清晰之功效。简直是小白程序员必备技能
如何分模块呢?
首先,创建三个文件,一个测试的源文件,一个游戏的源文件,一个游戏的头文件
测试的源文件专门用来存放测试所需要用的代码(废话文学我算是把玩明白了),游戏
的源文件来存放实现游戏逻辑的代码,而游戏的头文件用来放各种头文件,和各种函数
声明。
1.2.2 打印菜单供用户选择(老菜单人了)
//这是测试源文件的代码
#include <stdio.h>
void menu()
{
printf("***********************\n");
printf("**1.play*******0.exit**\n");
printf("***********************\n")//让用户输入数字选择
}
void test()
{
int input=0;
menu();//调用个menu函数这里就是打印出来的菜单
scanf("%d",&input);
do
{
switch(input)
{
case 1:
{
break;
}
case 2:
{
printf("游戏退出\n");
}
default:
{
printf("请重新输入");
}
}while(input);
}
}
int main()
{
test();//在主函数里只调用个test函数剩下的由test函数来完成
}
1.2.3 操作游戏函数
游戏的测试文件部分
1.三子棋本质上就是在操作一个二维数组在不同位置上放置棋子,为了拓展性够高我们在表示行和列统一定义两个符号(也就是常量)
那么常量怎么定义呢?
在游戏的头文件里面定义 ,我们现在要用ROW,COL.就要包含这个头文件
2.将所有数组初始化为空格方便我们后期在空格里存放棋子(先在头文件中声明,再在game的源文件中定义)。
3棋盘打印好,就可以下棋了,先玩家下然后电脑下棋下完一次打印一次棋盘方便看见棋下在哪里
4判断输赢
//这是测试源文件的代码
#include "game.h"//在调用自己的头文件的时候用""
void menu()
{
printf("***********************\n");
printf("**1.play*******0.exit**\n");
printf("***********************\n");//让用户输入数字选择
}
void game()
{
char board[ROW][COL] = { 0 };//操作这个二维数组用于放置棋子
InitBoard(board, ROW, COL);//初始化这个二维数组,移步在下面的游戏函数看
Display_Board(board, ROW, COL);//将棋盘现实出来或者打印出来
char ret = is_win(board, ROW, COL);
while (1)//循环直到判断出输赢跳出
{
Player_move(board,ROW,COL);//玩家下棋
Display_Board(board,ROW,COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')//这个判断条件在棋盘每打印一次之后就判断一次,直到条件成立
{
break;
}
Computer_move(board,ROW,COL);//电脑下棋
Display_Board(board,ROW,COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家赢\n");
}
if (ret == '#')
{
printf("电脑赢\n");
}
if (ret == 'Q')
{
printf("平局\n");
}
}
void test()
{
int input = 0;
do
{
menu();//调用个menu函数这里就是打印出来的菜单
scanf("%d", &input);
switch (input)
{
case 1:
{
game();//创建一个游戏函数我们来开始进入游戏了Let`s go
break;
}
case 2:
{
printf("游戏退出\n");
}
default:
{
printf("请重新输入");
}
}
}while (input);
}
int main()
{
srand((unsigned int)time(NULL));
test();//在主函数里只调用个test函数剩下的由test函数来完成
}
游戏的头文件
我们可以将所有的头文件都放在我们创建的头文件最后直接统一调用这个头文件
//这是三子棋游戏的头文件
#include <stdio.h>
#define ROW 3
#define COL 3
#include <stdlib.h>
#include <time.h>
void InitBoard(char board[ROW][COL],int row,int col);//先将这个函数声明否则会有警告
void Display_Board(char board[ROW][COL],int row,int col);
void Player_move(char board[ROW][COL],int row,int col);
void Computer_move(char board[ROW][COL],int row,int col);
char is_win(char board[ROW][COL],int row,int col);
游戏的源文件
初识化二维数组
打印棋盘
3.打印棋盘
首先要考虑在一个普通人看见这个棋盘的时候会样输入下标,在输入的时候就按照普通人的角度输入,我们再将输入的内容转换为真正二维数组的下标,其实输入的值跟最后执行的值是不一样的。
而对于计算机来说就没有那么多限制,只需要将随机数的范围限制在数组小标限定的范围内即可
随机数:rand()函数,需要调用srand()函数,srand()函数的参数也是一个无符号整型的随机数,而这个随机数从哪来呢,这就要引入时间戳的概念了。时间戳:就是现在时间与第一台计算机时间的差值,用time来实现。因此srand((unsigned int)time(NULL));
4.判断输赢
我们先来看总共可以有几种情况
1玩家赢 返回#
2 电脑赢 返回*
3 平局 返回Q
4 以上三种都不是 继续 返回 C
在判断行列是否为空的时候不能直接将一个确定的数组填进去,只能依据循环的特点判断
返回亦如此
//这是游戏的源文件
#include "game.h"
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';//将每个元素遍历并将其赋值为空格用于我们来放置棋子
}
}
}
//显示(打印)棋盘(效果看图一)
void Display_Board(char board[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 ", board[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 Player_move(char board[ROW][COL], int row, int col)
{
printf("玩家走:>");
int i = 0;
int j = 0;
while (1)
{
scanf("%d%d", &i, &j);//scanf必须写在循环里否则里面的如果没走if直接死循环else
if (i >= 1 && i <= row && j >= 1 && j <= col)//在玩家眼中没有元素小标的概念所以让玩家正常输入
{
if (board[i - 1][j - 1] == ' ')//我们将其转换为计算机可以看懂的语言,如果为空就可以下棋
{
board[i - 1][j - 1] = '*';
break;
}
else//如果不是为空就表示已经被占
printf("此位置已经被占");
}
else
printf("坐标输入错误请重新输入");
}
}
//电脑走
void Computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;//随机函数需要调用srand实现(在主函数内)引头文件<stdlib.h>(在头文件中)
y = rand() % col;//%col让随机数的范围控制在0~2的范围内
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//判断输赢
int is_full(char board[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 (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row;i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
}
for (i = 0; i < col;i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
{
return board[1][1];
}
int ret = is_full(board, row, col);
if (ret == 0)
{
return 'C';
}
else
{
return 'Q';
}
}