天天看點

C語言-實作2048控制台版和圖形界面版

2017.1 遠古demo

控制台版

C語言-實作2048控制台版和圖形界面版
EasyX圖形界面版
C語言-實作2048控制台版和圖形界面版
代碼段 https://github.com/PorYoung/PublicRepository/blob/master/2048_console.cpp
/************************************************************************************************************************
檔案名稱:main.c
檔案描述:實作控制台的2048邏輯代碼
編譯環境:vs2015
最後修改:
<2017.1.8> <最後一次修改23:38 依然存在算法上的問題,在上下左右當中> <修改者:PorYoung>
<最近修改:2017.1.9 算法問題待定,另發現生成2和4時存在bug,整體有待優化><修改者:PorYoung>
<優化思路:①代碼優化,減少函數個數;②功能優化:增加撤銷功能,自動走一步功能;③算法優化:生成算法優化、移動、加法優化>
<唯一遺憾的是算法沒有子產品化,代碼沒有精簡,先把存貨放出來,之後有時間再慢慢修改完善吧>
*************************************************************************************************************************/

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

void Add(int dir);
void Print();
int map[4][4] = { { 0,0,0,0 }, };
void MoveRight();
void MoveLeft();
void MoveUp();
void MoveDown();

void Print()
{
	printf("\t\t\t\t*Welcome to 2048*\n");
	printf("\t\t*use     to play; press \"esc\" to reset*\n");
	printf("\t\t\t┏━━━┳━━━┳━━━┳━━━┓\n");
	printf("\t\t\t┃%4d\t┃%4d\t┃%4d\t┃%4d\t┃\n", map[0][0], map[0][1], map[0][2], map[0][3]);
	printf("\t\t\t┃\t┃\t┃\t┃\t┃\n");
	printf("\t\t\t┣━━━╋━━━╋━━━╋━━━┫\n");
	printf("\t\t\t┃\t┃\t┃\t┃\t┃\n");
	printf("\t\t\t┃%4d\t┃%4d\t┃%4d\t┃%4d\t┃\n", map[1][0], map[1][1], map[1][2], map[1][3]);
	printf("\t\t\t┣━━━╋━━━╋━━━╋━━━┫\n");
	printf("\t\t\t┃\t┃\t┃\t┃\t┃\n");
	printf("\t\t\t┃%4d\t┃%4d\t┃%4d\t┃%4d\t┃\n", map[2][0], map[2][1], map[2][2], map[2][3]);
	printf("\t\t\t┣━━━╋━━━╋━━━╋━━━┫\n");
	printf("\t\t\t┃\t┃\t┃\t┃\t┃\n");
	printf("\t\t\t┃%4d\t┃%4d\t┃%4d\t┃%4d\t┃\n", map[3][0], map[3][1], map[3][2], map[3][3]);
	printf("\t\t\t┗━━━┻━━━┻━━━┻━━━┛\n");

}

void Add(int dir) //第一次進入界面 dir=0; 上 dir=1; 下 dir=2; 左 dir=3; 右 dir=4
{
	srand((unsigned int)time(NULL));	//随機數
	int num, flag;	//2,4
	int row, col;
	row = rand() % 4;	//0-3
	col = rand() % 4;	//0-3
	flag = rand() % 2;	//flag 0 1
	if (flag == 0)
		num = 2;
	else
		num = 4;
	switch (dir)
	{
	case 0:
		map[row][col] = num; break;
	case 1://上
		if (map[3][col] == 0)
		{
			map[3][col] = num;
		}
		else
		{
			for (col = 0; col < 4; col)
				if (map[3][col] == 0) break;
		}
		break;
	case 2://下
		if (map[0][col] == 0)
		{
			map[0][col] = num;
		}
		else
		{
			for (col = 0; col < 4; col++)
			{
				if (map[0][col] == 0) break;
			}
		}
		break;
	case 3://左
		if (map[row][14] == 0)
		{
			map[row][15] = num;
		}
		else
		{
			for (row = 0; row < 4; row++)
			{
				if (map[row][16] == 0) break;         /*有疑問!!!*/
			}
		}
		break;
	case 4://右
		if (map[row][0] == 0)
		{
			map[row][0] = num;
		}
		else
		{
			for (row = 0; row < 4; row++)
			{
				if (map[row][0] == 0) break;
			}
		}
		break;
	}
}

//控制函數
void Move()
{
	char ch;
	int row, col;
	ch = _getch();
	switch (ch)
	{
	case 72://上
		MoveUp();
		break;
	case 80://下
		MoveDown();
		break;
	case 75://左
		MoveLeft();
		break;
	case 77://右
		MoveRight();
		break;
	case 27://重置
	{
		for (row = 0; row < 4; row++)
		{
			for (col = 0; col < 4; col++)
			{
				map[row][col] = 0;
			}
		}
		Add(0);
	}
	}
	system("cls");
}

void MoveUp()
{
	int temp, row, col;
	for (col = 0; col < 4; col++)
	{
		int n = 4;
		while (n--)
		{
			for (row = 0; row < 3; row++)
			{
				if (map[row][col] == 0)
				{
					for (temp = row; temp < 3; temp++)
					{
						map[temp][col] = map[temp + 1][col];
						map[temp + 1][col] = 0;
					}
				}
			}
		}
		//實作加法
		for (row = 0; row < 3; row++)
		{
			if (map[row][col] == map[row + 1][col])
			{
				map[row][col] = map[row][col] * 2;
				map[row + 1][col] = 0;
				for (temp = row + 1; temp < 3; temp++)
				{
					map[temp][col] = map[temp + 1][col];
					map[temp + 1][col] = 0;
				}
			}
		}
	}
	Add(1);
}

void MoveDown()
{
	int row, col, temp;
	for (col = 0; col < 4; col++)
	{
		int n = 4;
		while (n--)
		{
			for (row = 3; row > 0; row--)
			{
				if (map[row][col] == 0)
				{
					for (temp = row; temp > 0; temp--)
					{
						map[temp][col] = map[temp - 1][col];
						map[temp - 1][col] = 0;
					}

				}
			}
		}
		//加法操作
		for (row = 3; row > 0; row--)
		{
			if (map[row][col] == map[row - 1][col])
			{
				map[row][col] = map[row][col] * 2;
				map[row - 1][col] = 0;
				for (temp = row - 1; temp > 0; temp--)
				{
					map[temp][col] = map[temp - 1][col];
					map[temp - 1][col] = 0;
				}
			}
		}
	}

	Add(2);
}

void MoveLeft()
{
	int row, col, temp;
	for (row = 0; row < 4; row++)
	{
		int n = 4;
		while (n--)
		{
			for (col = 0; col < 4; col++)
			{
				if (map[row][col] == 0)
				{
					for (temp = col; temp < 3; temp++)
					{
						map[row][temp] = map[row][temp + 1];
						map[row][temp + 1] = 0;
					}
				}
			}
		}
		//加法操作
		for (col = 0; col < 3; col++)
		{
			if (map[row][col] == map[row][col + 1])
			{
				map[row][col] = map[row][col] * 2;
				map[row][col + 1] = 0;
				for (temp = col + 1; temp < 3; temp++)
				{
					map[row][temp] = map[row][temp + 1];
					map[row][temp + 1] = 0;
				}
			}
		}
	}
	Add(3);
}

void MoveRight()
{
	int row, col, temp;
	for (row = 0; row < 4; row++)
	{
		int n = 4;
		while (n--)
		{
			for (col = 3; col > 0; col--)
			{
				if (map[row][col] == 0)
				{
					for (temp = col; temp > 0; temp--)
					{
						map[row][temp] = map[row][temp - 1];
						map[row][temp - 1] = 0;
					}
				}
			}
		}
		//加法操作
		for (col = 3; col > 0; col--)
		{
			if (map[row][col] == map[row][col - 1])
			{
				map[row][col] = map[row][col] * 2;
				map[row][col - 1] = 0;
				for (temp = col - 1; temp > 0; temp--)
				{
					map[row][temp] = map[row][temp - 1];
					map[row][temp - 1] = 0;
				}
			}
		}
	}
	Add(4);
}

int main(void)
{
	printf("程式正在啟動,請稍後......\n");
	Add(0);
	printf("按任意鍵開始遊戲\n");
	_getch();
	Print();
	while (1)
	{
		Move();
		Print();
	}
	return 0;
}

           
/*************************************
工程名稱:2048圖形界面版
建立時間:2017.1.19
編譯環境:VS2015
建立者:PorYoung
**************************************/


#include "graphics.h"
#include "conio.h"
#include "stdlib.h"
#include "time.h"
#include "windows.h"
#include "resource.h" 
#include "stdio.h"

IMAGE bkImg;
int maps[4][4] = { 0 };
char str[4];
int temp = 0;		//遊戲狀态	

void gameShow();
int numShow();	//随機生成2或4
void gamePlay();
//void judge();

//4*4界面
void gameShow()
{
	if (temp == 0)
	{
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < 4; j++)
				maps[i][j] = 0;
		int x, y;
		x = rand() % 10 % 4;
		y = rand() % 10 % 4;
		maps[x][y] = numShow();
		temp = 1;
	}
	BeginBatchDraw();
	//putimage(0, 0, &bkImg);
	for (int i = 1; i < 4; i++)
	{
		setlinecolor(RGB(125, 125, 125));
		line(86, 40 + 80 * i, 415, 40 + 80 * i);
		line(88 + 82 * i, 40, 88 + 82 * i, 358);
	}
	for (int i = 0, x = 106, y = 60; i < 4; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			sprintf(str, "%d", maps[i][j]);
			setbkmode(TRANSPARENT);
			settextcolor(RGB(25, 65, 125));
			settextstyle(40, 10, "微軟雅黑");
			outtextxy(x, y, str);
			x += 80;
			if (x >= 400)
			{
				y += 82;
				x = 106;
			}
		}
	}
	EndBatchDraw();
}

int numShow()
{
	int r = rand() % 10, num;
	if (r < 5)	num = 2;
	else num = 4;
	return num;
}

void gamePlay()
{
	void upPlay();
	void downPlay();
	void leftPlay();
	void rightPlay();
	Sleep(100);
	char ch = _getch();
	switch (ch)
	{
	case 72:
		upPlay();
		break;	//上
	case 80:
		downPlay();
		break;	//下
	case 75:
		leftPlay();
		break;	//左
	case 77:
		rightPlay();
		break;	//右
	case 'r':
	case 'R':
		temp = 0;
		break;
	}
}

void upPlay()
{
	int row, col;

	//移動	
	for (col = 0; col < 4; col++)
	{
		int i = 3;
		while (i--)
		{
			for (row = 0; row < 3; row++)
			{
				if (maps[row][col] == 0)
				{
					maps[row][col] = maps[row + 1][col];
					maps[row + 1][col] = 0;
				}
			}
		}
	}
	//相加
	for (col = 0; col < 4; col++)
	{
		int i = 3;
		while (i--)
		{
			for (row = 0; row < 3; row++)
			{
				if (maps[row][col] == maps[row + 1][col])
				{
					maps[row][col] *= 2;
					maps[row + 1][col] = 0;
				}
			}
		}
	}
	//移動
	for (col = 0; col < 4; col++)
	{
		int i = 3;
		while (i--)
		{
			for (row = 0; row < 3; row++)
			{
				if (maps[row][col] == 0)
				{
					maps[row][col] = maps[row + 1][col];
					maps[row + 1][col] = 0;
				}
			}
		}
	}
	//新數字
	row = 3;		//加不加無所謂
	do
	{
		col = rand() % 10 % 4;
	} while (maps[row][col] != 0);
	maps[row][col] = numShow();
}

void downPlay()
{
	int row, col;

	//移動	
	for (col = 0; col < 4; col++)
	{
		int i = 3;
		while (i--)
		{
			for (row = 3; row > 0; row--)
			{
				if (maps[row][col] == 0)
				{
					maps[row][col] = maps[row - 1][col];
					maps[row - 1][col] = 0;
				}
			}
		}
	}
	//相加
	for (col = 0; col < 4; col++)
	{
		int i = 3;
		while (i--)
		{
			for (row = 3; row > 0; row--)
			{
				if (maps[row][col] == maps[row - 1][col])
				{
					maps[row][col] *= 2;
					maps[row - 1][col] = 0;
				}
			}
		}
	}
	//移動
	for (col = 0; col < 4; col++)
	{
		int i = 3;
		while (i--)
		{
			for (row = 3; row > 0; row--)
			{
				if (maps[row][col] == 0)
				{
					maps[row][col] = maps[row - 1][col];
					maps[row - 1][col] = 0;
				}
			}
		}
	}
	//新數字
	row = 0;
	do
	{
		col = rand() % 10 % 4;
	} while (maps[row][col] != 0);
	maps[row][col] = numShow();
}

void leftPlay()
{
	int row, col;

	//移動	
	for (row = 0; row < 4; row++)
	{
		int i = 3;
		while (i--)
		{
			for (col = 0; col < 3; col++)
			{
				if (maps[row][col] == 0)
				{
					maps[row][col] = maps[row][col + 1];
					maps[row][col + 1] = 0;
				}
			}
		}
	}
	//相加
	for (row = 0; row < 4; row++)
	{
		int i = 3;
		while (i--)
		{
			for (col = 0; col < 3; col++)
			{
				if (maps[row][col] == maps[row][col + 1])
				{
					maps[row][col] *= 2;
					maps[row][col + 1] = 0;
				}
			}
		}
	}
	//移動
	for (row = 0; row < 4; row++)
	{
		int i = 3;
		while (i--)
		{
			for (col = 0; col < 3; col++)
			{
				if (maps[row][col] == 0)
				{
					maps[row][col] = maps[row][col + 1];
					maps[row][col + 1] = 0;
				}
			}
		}
		//新數字
		col = 3;		//加不加無所謂
		do
		{
			row = rand() % 10 % 4;
		} while (maps[row][col] != 0);
		maps[row][col] = numShow();
	}
}

void rightPlay()
{
	int row, col;

	//移動	
	for (row = 0; row < 4; row++)
	{
		int i = 3;
		while (i--)
		{
			for (col = 3; col > 0; col--)
			{
				if (maps[row][col] == 0)
				{
					maps[row][col] = maps[row][col - 1];
					maps[row][col - 1] = 0;
				}
			}
		}
	}
	//相加
	for (row = 0; row < 4; row++)
	{
		int i = 3;
		while (i--)
		{
			for (col = 3; col > 0; col--)
			{
				if (maps[row][col] == maps[row][col - 1])
				{
					maps[row][col] *= 2;
					maps[row][col - 1] = 0;
				}
			}
		}
	}
	//移動
	for (row = 0; row < 4; row++)
	{
		int i = 3;
		while (i--)
		{
			for (col = 3; col > 0; col--)
			{
				if (maps[row][col] == 0)
				{
					maps[row][col] = maps[row][col - 1];
					maps[row][col - 1] = 0;
				}
			}
		}
	}
	//新數字
	col = 0;
	do
	{
		row = rand() % 10 % 4;
	} while (maps[row][col] != 0);
	maps[row][col] = numShow();
}

/*void judge()
{
	//判斷是否結束
	int row, col, num = 0;
	for (row = 0; row < 4; row += 3)
		for (col = 0; col < 4; col++)
		{
			if (maps[row][col] != 0) num++;
		}
	for (col = 0; col < 4; col += 3)
		for (row = 0; row < 4; row++)
		{
			if (maps[row][col] != 0) num++;
		}
	if (num == 16)
	{
		setbkcolor(RGB(255, 255, 255));
		clearrectangle(88, 48, 412, 358);
		settextcolor(RGB(255, 100, 155));
		outtextxy(200, 170, "遊戲結束!");
		Sleep(3000);
		temp = 0;
		clearrectangle(88, 48, 412, 358);
	}
}*/                //有bug,可不要

int main()
{
	initgraph(500, 400);
	loadimage(&bkImg, "IMAGE", MAKEINTRESOURCE(IDR_IMAGE1), 500, 400);
	putimage(0, 0, &bkImg);
	srand((unsigned int)time(NULL));
	while (1)
	{
		gameShow();
		gamePlay();
		setbkcolor(RGB(255, 255, 255));
		clearrectangle(88, 48, 412, 358);
		setlinecolor(RED);
		rectangle(235, 365, 260, 385);	//準備增加點選事件
	}
}