【C语言小游戏】“三子棋”教学

发布于:2023-01-18 ⋅ 阅读:(451) ⋅ 点赞:(0)

今天来教学大家学习用C语言来制作三子棋小游戏,希望我的文章可以帮助到你。

1.“游戏菜单”

“游戏菜单”

1.游戏进入时需要向玩家提供菜单,让玩家选择玩游戏,还是退出游戏.
2.为了增加可玩性,让玩家再玩过后可以再次选择玩游戏还是退出游戏.
3.如果玩家输入错误,可以重新输入

代码如下:

    do 
	{
		menu();
		printf("请输你的选择:>");
		scanf("%d", &input);
		switch (input) 
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default :
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);

2.“初始化数组”

“初始化数组”
由于三子棋的特性,这里我们可以用一个字符数组来存储棋盘中的棋子,设置完数组后需要对数组中的每一个元素初始化为空格(因为空格看不见又可以占位置)
char board[ROW][COL] = {0};

代码如下:

//初始化棋盘
void init_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++) 
		{
			board[i][j] = ' ';
		}
	}
}

其中的ROW和COL通过定义有利于后期对于棋盘的修改

#define ROW 3
#define COL 3

3.“打印棋盘”

“打印棋盘”
我们需要将初始化的棋盘呈现给玩家观看,才能让玩家知道要下在棋盘的那个位置,所以我们又需要一个打印函数

代码如下:

//打印棋盘
void display_board(char board[ROW][COL], int row, int col)
{
	// c | c | c 
	//---|---|---
	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) //最后的分割行不要
		{
			for (j = 0; j < col; j++) 
			{
				printf("---");
				if (j < col - 1) //最后的竖杆不要
				{
					printf("|");
				}
			}
		}
		printf("\n");
	}
}

4.“玩家下棋”

“玩家下棋”
在展示给玩家棋盘后,我们需要再创建一个函数用于玩家下棋
player_move(board, ROW, COL);//玩家下棋

玩家可以选择棋盘的位置下棋,需要注意的是大部分玩家数数都是从1开始数,所以我们的代码也要进行相应的调整。

我们需要判断玩家输入的坐标是否具有合法性,并且判断输入的坐标是否已经被占用。

代码如下:

//玩家下棋
void player_move(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] = 'O';
				break;
			}
			else
			{
				printf("坐标已被占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

5.“电脑下棋”

“电脑下棋”
在玩家下棋完后就要让电脑下棋了,所以创建一个函数用于电脑下棋
computer_move(board, ROW, COL);//电脑下棋

由于需要使用到随机数,所以要先在主函数中使用srand()函数

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

并且还有声明两个头文件

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

代码如下:

//电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{	
	printf("电脑下棋\n");
	while (1)
	{
		int x = rand() % row;//生成0~row-1的随机数
		int y = rand() % col;//生成0~col-1的随机数
		if (board[x][y] == ' ')
		{
			board[x][y] = 'X';
			break;
		}
	}
}

6.“判断状态”

“判断状态”
在每一次下棋后棋盘可能会有四种状态,我们用四个字符来表示四种状态分别为

1.玩家获胜——‘O’
2.电脑获胜 ——‘X’
3.平局——‘Q’
4.棋盘未下满,继续下棋——‘C’

我们可以通过创建用于判断的函数并获取函数的返回值来判断棋盘的状态

ret = is_win(board, ROW, COL);

除了C棋盘未满要继续下棋以外,其它字符都要退出循环

if (ret != 'C')
		{
			break;
		}

退出循环后进行判断

if (ret == 'O')
	{
		printf("玩家获胜\n");
	}
	else if(ret=='X')
	{
		printf("你输啦\n");
	}
	else if(ret=='Q')
	{
		printf("平局\n");
	}

代码如下:

//判断游戏状态
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[1][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[1][1] == board[2][0] && board[0][2] != ' ')//斜判断
	{
		return board[0][0];
	}

	if (is_full(board, row, col) == 1)//平局判断
	{
		return 'Q';
	}
	 
	return 'C';//继续判断

}

其中棋盘是否填满需要另外的函数判断

//判断是否填满
int is_full(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;
}

完整代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define ROW 3
#define COL 3

//初始化棋盘
void init_board(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);

void menu()
{
	printf("****************\n");
	printf("****1.玩游戏****\n");
	printf("****0.退出游戏**\n");
	printf("****************\n");
}

void game()
{
	char ret = 0;
	//数据的存储需要一个3*3的二维数组
	char board[ROW][COL] = { 0 };
	init_board(board, ROW, COL);//初始化数组
	display_board(board, ROW, COL);
	//玩游戏
	while (1)
	{
		player_move(board, ROW, COL);//玩家下棋
		system("cls");//清屏
		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 == 'O')
	{
		printf("玩家获胜\n");
	}
	else if (ret == 'X')
	{
		printf("你输啦\n");
	}
	else if (ret == 'Q')
	{
		printf("平局\n");
	}
}

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;
}

//初始化棋盘
void init_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++)
		{
			board[i][j] = ' ';
		}
	}
}

//打印棋盘
void display_board(char board[ROW][COL], int row, int col)
{
	// c | c | c 
	//---|---|---
	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) //最后的分割行不要
		{
			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)
{
	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] = 'O';
				break;
			}
			else
			{
				printf("坐标已被占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

//电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	while (1)
	{
		int x = rand() % row;//生成0~row-1的随机数
		int y = rand() % col;//生成0~col-1的随机数
		if (board[x][y] == ' ')
		{
			board[x][y] = 'X';
			break;
		}
	}
}

//判断是否填满
int is_full(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 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[1][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[1][1] == board[2][0] && board[0][2] != ' ')//斜判断
	{
		return board[0][0];
	}

	if (is_full(board, row, col) == 1)//平局判断
	{
		return 'Q';
	}

	return 'C';//继续判断

}

网站公告

今日签到

点亮在社区的每一天
去签到