c语言实现一个简易三子棋

本文详细介绍了如何使用C语言编程实现一个简单的三子棋游戏,包括游戏流程、主要函数如`main()`、`game()`、`InitBoard()`、`DisplayBoard()`、`PlayerMove()`、`ComputerMove()`和`IsWin()`的实现,以及玩家和电脑的胜负判断。代码中,电脑采用随机策略下棋,游戏结束后能显示玩家胜、电脑胜或平局的结果。
摘要由CSDN通过智能技术生成

本文章主要目的是讲解如何实现一个三子棋小游戏,实现人机对战,人先手,电脑下棋为随机下棋。

建议先将全部代码复制下来,再阅读文章。

不足之处欢迎指出!

目录

一、代码实现步骤

    1.main()函数的设计

    2.主体函数game()的实现

二、运行测试

        1.玩家赢

         2.电脑赢

         3.平局

 三、代码

        1.头文件game.h代码

        2.源文件game.c的代码

        3.源文件test.c代码


 

 


一、代码实现步骤

    1.main()函数的设计

          main函数代码:

int main() {
	int input = 0;
	do {
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
		case 0:
			break;
		default:
			printf("输入错误,请重新选择:\n");
			break;
		}
	} while (input);
	return 0;
}

        这里我们用do while()循环来实现重复选择,选择1进入游戏,选择0退出游戏。

        而menu()函数为我们实现了一个菜单,如下图:  

dfe2af5be03b41d0a18f0b2278f5c471.png

        menu菜单代码:

void menu() {
	printf("**********************************\n");
	printf("******         1.play       ******\n");
	printf("******         0.exit       ******\n");
	printf("**********************************\n");
}

    2.主体函数game()的实现

        第二部分就是实现上述代码中的game()部分,在这个函数中我们将具体实现三子棋游戏的诸多功能:实现棋盘,玩家下棋,电脑下棋,判断输赢。

       game()函数代码如下:

void game() {
	//创建一个3×3的二维数组(棋盘),存放棋子
	char board[ROW][COL];
	//初始化数组&棋盘
	InitBoard(board, ROW, COL);
	//显示棋盘
	DisplayBoard(board,ROW ,COL);
	char ret = ' ';
	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");
	}
}

        上述代码中,首先进行的是创建一个3×3的棋盘,使用二维数组形式创建,其中ROW为棋盘的行(值为3),COL为棋盘的列(值为3),而玩家下棋使用'*'表示,电脑下棋使用'#'表示,所以定义为char型数组。

        下一步是棋盘的初始化,将棋盘内内容置空,也就是将数组board里面的所有项设为字符空格'  ',到时打印棋盘的时候这些位置显示空格,玩家或电脑下棋后将空格改为相应符号。 

        初始化函数InitBoard(char board[ROW][COL], int row, int col)代码:

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col) {
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < row; j++) {
			board[i][j] = ' ';
		}
	}
}

        后面一部则是打印棋盘,实现DisplayBoard(char board[ROW][COL], int row, int col)函数,而实现的棋盘效果如下图:

05958464cb264fcfaf08d5c10b7efa3c.png

棋盘

 

        打印棋盘代码:

//打印棋盘
void DisplayBoard(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("|");
			else
				printf("\n");
		}
		if (i < row - 1) {
			for (j = 0; j < col; j++) {
				printf("---");
				if (j < col - 1)
					printf("|");
			}
		}
		printf("\n");
	}
	
}

 

        这里我们的实现思路是用‘|’(竖杠)以及‘---’(三个减号)将二维数组内的元素分隔开,形成一个九宫格。

       具体实现要用到两个for循环从左到右,从上到下依次打印出棋盘。

 

        接下来用while循环来实现下棋功能,而下棋的步骤是玩家下棋>电脑下棋>玩家下棋>电脑下棋,如此循环。实际上生活中进行三子棋游戏在下棋之后还要进行判断,谁赢了?所以真实步骤为玩家下棋>判断输赢>电脑下棋>判断输赢,而具体实现的时候我们还需要在下棋和判断输赢之间添加一个打印棋盘的步骤。

        玩家下棋用函数PlayerMove(char board[ROW][COL], int row, int col)实现:

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col) {
	printf("玩家下棋:>\n");
	printf("请输入下棋坐标:>");
	int x = 0;
	int y = 0;
	while (1) {
		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("该坐标已被占用,请重新输入:>");
				continue;
			}
		}
		else {
			printf("输入坐标已超出范围,请重新输入:>");
			continue;
		}
	}
}

        这里大家应该都能看懂,简单说下就是输入两个数字(空格隔开),这两个数字对应你要下的位置,然后将这个位置对应的数组元素赋值为'*',如果位置以及被下,或者超出范围就会提示重新输入。

        而电脑下棋我们设计的是随机下棋,就是生成两个随机数x,y,也就是生成一个随机坐标,这里要用到rand库函数,如何限制这个数的生成范围呢?我们可以用随机生成的数%3,这样我们就能得到1~3之间的数。这个随机生成的数还需要一个库函数void srand(unsigned int seed)来确保rand()函数生成的数是真正的随机数。rand()生成的数会根据srand内的参数来生成,所以我们可以将时间传入进去。这里我们需要两个头文件:

#include <stdlib.h>
#include <time.h>

        而srand函数需要写在main函数中,写法如下

srand((unsigned int)time(NULL));

        而电脑下棋函数ComputerMove(char board[ROW][COL], int row, int col)代码:

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col) {
	printf("电脑下棋:>\n");
	while(1) {
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ') {
			board[x][y] = '#';
			break;
		}
		continue;
	}
}

        后面我们用IsWin(char board[ROW][COL], int row, int col)来实现对输赢的判断:

//判断输赢
//'*'玩家赢
//'#'电脑赢
//'Q'平局
//'C'继续

char IsWin(char board[ROW][COL], int row, int col) {
	//判断上下三行是否有一行全相等,相等返回其中一个的值
	for (int 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 (int 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[2][0] == board[1][1] && board[1][1] == board[0][2] && board[2][0] != ' ') {
		return board[2][0];
	}
	//判断棋盘是否已满,已满返回Q
	if (IsFull(board,ROW,COL)) {
		return 'Q';
	}
	//上述都不成立返回C
	return 'C';
}

        上面代码每一行都有详细注释,整体功能就是当出现三个连一起的‘*’时,返回一个‘*’,出现三个连一起的‘#’时,返回一个‘#’,如果都没有判断棋盘是否已满,棋盘满了,返回一个‘Q’,棋盘没满,返回‘C’。而所有返回的数在外部用一个ret来接收。

        我们用接收到的‘*’表示玩家赢,用‘#’表示电脑赢,用‘Q’表示平局,用‘C’表示前三种可能都没有发生继续下棋。

        而如果ret接收到的数据!=‘C’(意思就是当出现了结果,也就是有一方赢了,或是平局了),我们就会跳出下棋这个循环,接着就是用if判断ret的值,输出结果(‘*’表示玩家赢,用‘#’表示电脑赢,用‘Q’表示平局)。

        判断棋盘是否已满的代码(平局):

int IsFull(char board[ROW][COL], int row, int col) {
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			if (board[i][j] == ' ') {
				return 0;
			}
		}
	}
	return 1;
}

        到这里所有实现步骤均已将完。

 


二、运行测试

        1.玩家赢

        c8d26987afd24dbdae0a5e9296e62ef3.png

        5da848703b494ab58e356aa0f6c44fdf.png

 c44da03935cf4d209f1ccf67a0c2eef3.png

         2.电脑赢

4b2e01521eb34160b854a8c8aba6dd97.png

 870fa42ed2384e728f5999e5c4749dd0.png

 69848bdd388b4d60a18f29da5e8535f2.png

         3.平局

f5b77831181a461594628f41f8579fd6.png

 ec1e89ccb76a43b591218af0bc34c136.png

 


 三、代码

        1.头文件game.h代码

#include <string.h>
#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);

        2.源文件game.c的代码

#include "game.h"

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col) {
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < row; j++) {
			board[i][j] = ' ';
		}
	}
}

//打印棋盘
void DisplayBoard(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("|");
			else
				printf("\n");
		}
		if (i < row - 1) {
			for (j = 0; j < col; j++) {
				printf("---");
				if (j < col - 1)
					printf("|");
			}
		}
		printf("\n");
	}
	
}

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col) {
	printf("玩家下棋:>\n");
	printf("请输入下棋坐标:>");
	int x = 0;
	int y = 0;
	while (1) {
		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("该坐标已被占用,请重新输入:>");
				continue;
			}
		}
		else {
			printf("输入坐标已超出范围,请重新输入:>");
			continue;
		}
	}
}

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col) {
	printf("电脑下棋:>\n");
	while(1) {
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ') {
			board[x][y] = '#';
			break;
		}
		continue;
	}
}

int IsFull(char board[ROW][COL], int row, int col) {
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			if (board[i][j] == ' ') {
				return 0;
			}
		}
	}
	return 1;
}

//判断输赢
//'*'玩家赢
//'#'电脑赢
//'Q'平局
//'C'继续

char IsWin(char board[ROW][COL], int row, int col) {
	//判断上下三行是否有一行全相等,相等返回其中一个的值
	for (int 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 (int 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[2][0] == board[1][1] && board[1][1] == board[0][2] && board[2][0] != ' ') {
		return board[2][0];
	}
	//判断棋盘是否已满,已满返回Q
	if (IsFull(board,ROW,COL)) {
		return 'Q';
	}
	//上述都不成立返回C
	return 'C';
}

        3.源文件test.c代码

#include "game.h"

void menu() {
	printf("**********************************\n");
	printf("******         1.play       ******\n");
	printf("******         0.exit       ******\n");
	printf("**********************************\n");
}

void game() {
	//创建一个3×3的二维数组(棋盘),存放棋子
	char board[ROW][COL];
	//初始化数组&棋盘
	InitBoard(board, ROW, COL);
	//显示棋盘
	DisplayBoard(board,ROW ,COL);
	char ret = ' ';
	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");
	}
}

int main() {
	srand((unsigned int)time(NULL));
	int input = 0;
	do {
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
		case 0:
			break;
		default:
			printf("输入错误,请重新选择:\n");
			break;
		}
	} while (input);
	return 0;
}

到这就结束啦,感谢您的阅读!

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值