学完了二维数组,为了加深我们对于二维数组的理解,这次我给大家带来了一个有趣得小程序,五子棋游戏。下面我们来看看吧。
五子棋游戏实现
程序分文件实现
一般情况下,在实际开发中,我们得一个项目都是要分很多文件的。比如函数的实现放在.c文件之中。函数的声明,全局变量的声明和头文件的包含。一般都放在.h文件中。
那么这样子做的优势是什么呢?试想一下如果我们把所有代码都写在一个文件之中。一个文件有上万行代码,这时候维护起来会变得极为困难。并且,多人协同开发也是个问题,总不能几十个人在一个文件里面写代码把。这时候就体现了分文件的优点了。代码便于管理。并且利于多人开发。
下面的这个五子棋小程序我们会分为三个文件。
主文件 main.c
函数实现文件 game.c
头文件 game.h
代码实现
//这是我们的主文件
//main.c
#include"game.h"//引用了自己创建的头文件。
void menu()
{
printf("*********************************\n");
printf("**** 1.game 0. exit ********\n");
printf("*********************************\n");
}
void game()
{
char arr[COL][ROW];
Init_board(arr, COL, ROW);
Print(arr, COL, ROW);
while (1)
{
Player_move(arr, COL, ROW);//创建数组用来生成棋盘
Print(arr, COL, ROW);//打印函数,用来打印棋盘
//判断玩家赢了没有
char is_win = Is_winner(arr, COL, ROW);//判断是否有人获胜
//这个函数我们规定。
//返回'*'则为玩家获胜
//返回'#'则为计算机获胜
//若是棋盘满了无人胜出则返回'Q'平局
//若是棋盘没满,且无人获胜就返回'C'游戏继续
if (is_win == '*')
{
printf("玩家赢了\n");
break;
}
else if (is_win == '#')
{
printf("计算机赢了\n");
break;
}
else if (is_win == 'Q')
{
printf("平局\n");
break;
}
Computer_move(arr, COL, ROW);//此函数是控制计算机落子的函数(当然我们这里设计的是随机落子)具体优化各位可以自行发挥超能力。
Print(arr, COL, ROW);
//判断电脑赢了没有
is_win = Is_winner(arr, COL, ROW);
if (is_win == '*')
{
printf("玩家赢了\n");
break;
}
else if (is_win == '#')
{
printf("计算机赢了\n");
break;
}
else if (is_win == 'Q')
{
printf("平局\n");
break;
}
}
}
int main()
{
srand((unsigned int)time(NULL));//设置随机数的起点
int input = 0;
do
{
menu();
printf("请选择:> ");
scanf("%d", &input);
switch (input)
{
case 1:
game();//游戏函数
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误!\n");
break;
}
} while (input);
return 0;
}
关于那个头文件为啥不用<>而是用""这里简单说一下,使用<>会优先从库中寻找该头文件,找不到的话再去项目路径下面去寻找。而如果使用自定义的头文件一般用双引号,这样可以先从项目路径下面寻找。
下面来看头文件
//game.h
#pragma once//这句代码可以防止头文件被重复包含
#define COL 5//行
#define ROW 5//列
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
void Init_board(char arr[COL][ROW], int col, int row);//初始化棋盘
void Print(char arr[COL][ROW], int col, int row);//打印棋盘
void Player_move(char arr[COL][ROW], int col, int row);//玩家落子
void Computer_move(char arr[COL][ROW], int col, int row);//计算机落子
//规定
//玩家赢返回 *
//计算机赢返回 #
//平局返回 Q
//没有结束继续游戏返回 C
char Is_winner(char arr[COL][ROW], int col, int row);//判断胜负
```头文件中包含了函数声明和宏定义
>下面是函数实现的.c文件
```c
//game.c
#include"game.h"//包含所有要引用的头文件和函数声明
//这是初始化函数,将二维数组的每个元素都初始化为' '空格
void Init_board(char arr[COL][ROW], int col, int row)
{
int i = 0;
int j = 0;
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
arr[i][j] = ' ';
}
}
}
//这是打印函数,可以让打印出来的棋盘更好看。主要都是循环,循环掌握了看起来应该不复杂。
void Print(char arr[COL][ROW], int col, int row)
{
int i = 0;
for (i = 0; i < col; i++)
{
for (int j = 0; j < row; j++)//打印棋盘内容
{
printf(" %c ", arr[i][j]);
if (j < row - 1)
printf("|");
}
printf("\n");
for (int k = 0; k < row; k++)//打印棋盘分隔符
{
printf("---");
if (k < row - 1)
{
printf("|");
}
}
printf("\n");
}
}
void Player_move(char arr[COL][ROW], int col, int row)//玩家落子
{
int x, y;
while (1)
{
printf("请玩家落子\n");
printf("请输入:> ");
scanf("%d %d", &x, &y);
//判断输入坐标是否合法(就是看输入的坐标是不是在数组的范围之内)
if (x-1 < col && y-1 < row && x-1 >= 0 && y-1 >= 0)
{
//判断该坐标点是否被占用
if (arr[x-1][y-1] == ' ')
{
arr[x-1][y-1] = '*';
break;//死循环直到有输入正确的坐标
}
else
printf("该点已有棋子,请重新输入\n");
}
else
{
printf("输入非法坐标 请重新输入\n");
}
}
}
void Computer_move(char arr[COL][ROW], int col, int row)//计算机落子
{
printf("计算机落子\n");
printf("Thinking \n");
Sleep(1000);
while (1)
{
int x = rand() % col;//生成合法范围内的随机数
int y = rand() % row;
//判断该点是否被占用
if (arr[x][y] == ' ')
{
arr[x][y] = '#';
break;
}
}
}
char Is_winner(char arr[COL][ROW], int col, int row)//判断胜负
{
//判断行
//外层循环,行。内层循环,列
for (int i = 0; i < col; i++)
{
char tmp = arr[i][0];
int flag = 0;
for (int j = 1; j < row; j++)
{
if (arr[i][j] == tmp&&tmp!=' ')
flag++;//用来标记,如果这一行都是一样的字符,就返回这个字符。
if (flag == row-1)
return tmp;
}
}
//判断列
for (int j = 0; j < row; j++)
{
char tmp = arr[0][j];
int count = 0;
for (int k = 1; k < col; k++)
{
if (tmp == arr[k][j]&&tmp!=' ')
count++;
if (count == col - 1)
{
return tmp;
}
}
}
//判断对角线
//这里判断的是主对角线
char cmp = arr[0][0];
int count = 0;
for (int i = 1; i < col; i++)
{
if (arr[i][i] == cmp)
count++;
if (count == col - 1)
{
return cmp;
}
}
//这里判断的是副对角线
cmp = arr[col-1][0];
count = 0;
for (int k = 1; k < row; k++)
{
if (cmp == arr[row - 1 - k][k])
count++;
if (count == row - 1)
return cmp;
}
//判断是否是平局,是则返回Q,不是则返回C继续游戏
for (int i = 0; i < col; i++)
{
for (int j = 0; j < row; j++)
{
if (arr[i][j] == ' ')
{
return 'C';
}
}
}
return 'Q';
}