一、三子棋介绍
相信大家都玩过三子棋小游戏,也知晓三子棋小游戏的规则,就是在一个三乘三棋盘上两方轮流下棋直到一方三颗棋子连成一条线,则胜利,若是棋盘下满了,则两方平局。那么接下来就让我们自己用C语言实现一个三子棋小游戏吧!
二、创建文件
首先,我们要知道实现一个小游戏不是短短几行代码就能搞定的!为了使我们的代码看起来更方便更高级,有更好的阅读体验。所以我们创建三个文件如图所示:
后续需要在test.c和game.c文件中包含#include "game.h"的头文件。
三、代码讲解
1.菜单函数和主函数
首先,每一个游戏都需要一个菜单,来了解这个游戏该怎么进行。
void menu(int input)
{
printf("******************************\n");
printf("******* 1.play *********\n");
printf("******* 2.exit *********\n");
printf("******************************\n");
}
int main()
{
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;
}
因为不管我们玩不玩游戏,这个游戏的菜单界面都要打印一遍,所以用do while 循环最合适。用swtich case语句来进行选择。
这里用input作为循环判断的条件,是因为我们都知道零为假,非零为真,我们用case 0退出游戏,同时也能退出循环。
2.game函数需要哪些功能
(1)打印一个棋盘
这是我们想要打印出来的棋盘,这很明显需要一个二维数组,而且这个二维数组的元素都为" "(空格),然后根据棋盘样式用printf修饰棋盘
void DisplayBoard(char board[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 ", board[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");
}
}
(2)玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋>:\n");
while (1)
{
printf("请输入下棋坐标,中间使用空格>:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')//可以落子
{
board[x - 1][y - 1] = '*';
break;
}
else//不能落子
{
printf("坐标已被占用,请重新输入\n");
}
}
else
{
printf("非法坐标请重新输入>:\n");
}
}
}
因为我们这里下棋是对数组下标进行修改,输入坐标进行判断,如果这个位置空着,那么就可以落子,但是如果输入的数组坐标越界,则让其重新输入,但是!玩家不会输入数组对应的下标也就是从0开始输入!所以我们这里需要把输入的x, y减少1!
(3)电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋>:\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
电脑下棋和玩家下棋规则一样,只不过落子为“#”。为了让电脑能随机给值进行下棋,这里我们需要引用一个rand函数数生成随机数,但是引用rand函数还需要引用一个srand函数,因此需要包含头文件<stdlib.h>和<time.h>。
srand((unsigned int)time(NULL));
这里为了防止电脑随机给值越界所以用电脑给出的随机值分别对行和列取余,这样随机数的范围就都在0-2之间。
(4)判断输赢/平局
char IsWin(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][0] == 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[0][0];
if (board[0][2] == board[1][1] && board[2][0] == board[1][1] && board[0][2] != ' ')
return board[0][2];
//平局
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
首先我们判断输赢的标准是:是否有人的三枚棋子连成一条线。
那么我们做出以下规定:
1.玩家赢返回“*”
2.电脑赢返回“#”
3.平局返回“Q”
4.继续下棋返回“C”
那么如何定义平局呢?平局就是棋盘已经满了,不能再继续落子!那么需要定义一个IsFull函数来判断是否棋盘已满。
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
四、代码整合
1.game.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL],int row,int col);//初始化棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);//打印棋盘
void PlayerMove(char board[ROW][COL], int row, int col);//玩家下棋
void ComputerMove(char board[ROW][COL], int row, int col);//电脑下棋
char IsWin(char board[ROW][COL], int row, int col);//判断输赢
int IsFull(char board[ROW][COL], int row, int col);//判断是否满盘
这里宏定义的优点在于如果后期需要改变棋盘大小,只需要在头文件里修改,不需要去翻找整个程序去修改!
2.game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[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 ", board[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");
}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋>:\n");
while (1)
{
printf("请输入下棋坐标,中间使用空格>:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')//可以落子
{
board[x - 1][y - 1] = '*';
break;
}
else//不能落子
{
printf("坐标已被占用,请重新输入\n");
}
}
else
{
printf("非法坐标请重新输入>:\n");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋>:\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char IsWin(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][0] == 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[0][0];
if (board[0][2] == board[1][1] && board[2][0] == board[1][1] && board[0][2] != ' ')
return board[0][2];
//平局
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
3.test .c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("******************************\n");
printf("******* 1.play *********\n");
printf("******* 0.exit *********\n");
printf("******************************\n");
}
void game()
{
char board[ROW][COL] = { 0 };//定义一个棋盘
InitBoard(board, ROW, COL);//初始化一个棋盘
DisplayBoard(board, ROW, COL);//打印棋盘
char ret = 0;
while (1)
{
//玩家下棋
PlayerMove(board, ROW,COL);
DisplayBoard(board, ROW, COL);//打印棋盘
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
printf("玩家赢\n");
else if(ret == '#')
printf("电脑赢\n");
else
printf("平局\n");
return 0;
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
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;
}
到此为止我们已经把一个三子棋游戏需要用到的函数全部都介绍完了,希望可以帮助到大家!如有需要改正的地方,希望大家能够指出,谢谢!