c语言实现三子棋

 一、游戏介绍

今天我们来用c语言实现一个非常经典游戏——三子棋。三字棋又名井字棋,游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子在横竖谢三线的任何一条线走成一条线就视为胜利。

二、游戏大概逻辑

根据图我们可以看出来,我们的三子棋代码有“打印菜单功能”,棋盘,玩家电脑依次下棋,判断输赢等多种功能。下面我们来一一实现这些功能。 

三、功能实现

 首先,我们来创建game.h文件来存放头文件及函数的声明

创建game.c文件来存放实现某种功能的函数

text.c存放测试函数。

1.game.h文件

 

#pragma once
//头文件包含
#include <stdio.h>
#include <time.h>
#include <stdlib.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文件实现函数功能 

a.棋盘格初始化

即定义一个3行3列的字符数组,再为它打印上分界线,形成一个棋盘

初始化时,把空格赋给该数组,形成空格棋盘,便于我们观察,与后续操作

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

 b.显示棋盘

显示棋盘,玩家和电脑每一步落子操作后,屏幕都显示最新棋盘信息

//打印棋盘
//就是将初始化的“ ”打印出来,并且打印格子
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("|");
		}
		printf("\n");
		if (i < row - 1)//打印横线
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");//同上
			}
		}
		printf("\n");
	}

}

c.玩家落子

用*代表玩家的棋子,对数组数组赋值,然后相对与落子

落子前,需要进行2步操作

第一个就是判断该坐标是否非法

第二个就是判读该坐标是否被占用

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家下棋:>\n");

	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("该坐标已被占用,请重新输入\n");
			}
		}
		else
		{
			printf("输入的坐标非法,请重新输入\n");
		}
	}
}

d.电脑落子

随机生成随机数代表代表电脑落子的坐标

然后其他注意点同玩家落子 

//电脑下棋
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;
		}
	}
}

e.判断输赢

电脑或者玩家每一次落子后都要进行一次游戏输赢的判断,若有一方胜利或者平局,游戏结束,反之游戏继续。

判断的思路就是利用if条件语句判断横竖斜三线是否有相同的棋子

//判断输赢
//玩家赢 - 返回'*'
//电脑赢 - 返回'#'
//平局   - 返回'Q'
//继续   - 返回'C'
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[0][i] == board[2][i] && board[0][i] != ' ')
		{
			return board[0][i];
		}
	}

	if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != ' ')
		//判断右斜线是否相同
	{
		return board[0][0];
	}
	
	if (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] != ' ')
		//判断左斜线是否相同
	{
		return board[0][2];
	}

	//判断是否平局(指棋盘满了,但是没有人赢)
	if (IsFull(board,ROW,COL))
	{
		return 'Q';
	}
	//继续
	return 'C';

}

 

平局判断

即,棋盘内已全部落满了棋子,但是没有一方胜利,视为平局 

//判断平局
int IsFull(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;
}

 3.text.c文件测试游戏逻辑

此文件的作用就是为了测试游戏逻辑,将一个个小模块按照游戏逻辑排布好,形成一个大游戏模型

#define _CRT_SECURE_NO_WARNINGS 1
//测试游戏逻辑
#include "game.h"
void menu();

void menu()//菜单函数
{
	printf("**********************************\n");
	printf("***********  1.play  *************\n");
	printf("***********  2.exit  *************\n");
	printf("**********************************\n");
}

void game()//游戏
{
	//存放数据需要3*3的二维数组
	char board[ROW][COL] = { 0 };

		//棋盘初始化
		InitBoard(board, ROW, COL);

		//打印棋盘
		DisplayBoard(board, ROW, COL);
		int 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);

			//ComputerMove(board);
			//打印棋盘
			DisplayBoard(board, ROW, COL);
			ret = IsWin(board, ROW, COL);
			if (ret != 'C')
			{
				break;
			}
		}

		if ('*' == ret)
		{
			printf("玩家赢\n");
		}
		else if ('#' == ret)
		{
			printf("电脑赢\n");
		}
		else if ('Q' == ret)
		{
			printf("平局\n");
		}

}

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("退出游戏!");
			break;
		default:
			printf("输入错误,请重新输入:>");
			break;
		}

	} while (input);//只要条件不为假,可以实现多次玩
	return 0;
}

总结

通过这个游戏的创建,我们可以初始认识到一个点,就是一个较大的系统,本质上都是由一个个小的模块构成的,如同我们的社会,是由一个一个家庭组成, 而家庭是由一个个的我们组成,由小到大。

以上就是本次的内容,内容较多,感谢各位耐心观看!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值