[Practice]山寨2048之Terminal版

吹水:

今日得闲没野做,就捻着搵点野料下。

我玩过2048,觉得规则挺简单的,应该挺好入手的。

毕竟,也是开源的。网上也存在很多教材或自定义,神马的。

于是,我本着尝试的态度,不看教程,能否山寨一个出来。

分析:去官网http://gabrielecirulli.github.io/2048/玩上几盘,一步一步地摸索其规则。

最后,经过一个下午和傍晚的时间,我实现了大致的功能,也不清楚是否和原版100%相同。

而且程序效率也不高,在此就不详解我自己的做法了。有兴趣的人,可自行参照网上的教程。

此帖,自娱自乐,目的只有一个:锻炼自己的编码能力和分析步骤。

备注:控制台版,使用C++语言

Grid.h

/***************************************************************
 *程序名称:2048
 *内容摘要:练习
 *其它说明:无
 *当前版本:V1.0
 *作    者:tbz
 *完成日期:2014年5月8日
 ***************************************************************/

#ifndef _GIRD_H_
#define _GIRD_H_

//实现4X4的方格,并提供移动、检测输赢等操作
class Grid
{
public:
	explicit Grid();

	void print();

	void move(char action);

	bool isWon();
	bool isLost();

private:
	int position[4][4];

	//这四个函数原理一致
	bool moveLeft();
	bool moveRight();
	bool moveUp();
	bool moveDown();

	//辅助函数
	bool isExistEqual(int row, int column);
	void generateEntry(int count);
	int& at(int row, int column);
	int random(int min, int max);
};

#endif

Grid.cpp

/***************************************************************
 *程序名称:2048
 *内容摘要:练习
 *其它说明:无
 *当前版本:V1.0
 *作    者:tbz
 *完成日期:2014年5月8日
 ***************************************************************/

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include "Grid.h"
using namespace std;

//从1开始计数
int& Grid::at(int row, int column)
{
	return position[row-1][column-1];
}

//生成某范围的随机数
int Grid::random(int min, int max)
{
	return ((rand() % (max-min+1)) + min);
}

//建立4X4表格,并初始化
Grid::Grid()
{
	srand(time(0));
	for (int row = 1; row <= 4; ++row)
		for (int column = 1; column <= 4; ++column)
		{
			at(row, column) = 0;
		}	

	//放置2个数
	generateEntry(2);
}

//生成几个数,不重复
void Grid::generateEntry(int count)
{
	int x = 0, y = 0, value = 0;
	for (int i = 0; i < count; ++i)
	{
		bool valid = false;
		while(!valid)
		{
			x = random(1, 4);
			y = random(1, 4);
			value = random(1, 2) * 2;
			if (!at(x, y))
			{
				valid = true;
				at(x, y) = value;
			}
		}
	}
}

//视图绘制
void Grid::print()
{
	cout << " ------------2048------------" << endl;
	cout << " ____________________________" << endl;
	for (int i = 1; i <= 4; ++i)
	{
		cout << "|";
		for (int j = 1; j <= 4; ++j)
		{
			int temp = at(i, j);
			if (temp)
				cout << " " << setw(4) << temp << ". ";
			else
				cout << " " << setw(4) << ‘ ‘ << ". ";
		}

		cout << "|" << endl;
	}
	cout << " ----------------------------" << endl;
}

void Grid::move(char action)
{
	bool moved = false;
	switch(action)
	{
		case ‘a‘:
		case ‘A‘:
			moved = moveLeft();
			break;
		case ‘d‘:
		case ‘D‘:
			moved = moveRight();
			break;
		case ‘w‘:
		case ‘W‘:
			moved = moveUp();
			break;
		case ‘s‘:
		case ‘S‘:
			moved = moveDown();
			break;
	}
	if (moved)
		generateEntry(1);
}

//检测
bool Grid::isWon()
{
	for (int i = 1; i <= 4; ++i)
	{
		for (int j = 1; j <= 4; ++j)
		{
			if (at(i, j) == 2048)
				return true;
		}
	}
	return false;
}

bool Grid::isExistEqual(int row, int column)
{
	bool ret = false;

	//行检测
	if (row == 1)
	{
		ret = (at(row, column) == at(row+1, column));
	}
	else if (row == 4)
	{
		ret = (at(row, column) == at(row-1, column));
	}
	else
	{
		ret = (at(row, column) == at(row-1, column)) && (at(row, column) == at(row+1, column));
	}

	//列检测
	if (column == 1)
	{
		ret = (at(row, column) == at(row, column+1));
	}
	else if (column == 4)
	{
		ret = (at(row, column) == at(row, column-1));
	}
	else
	{
		ret = (at(row, column) == at(row, column-1)) && (at(row, column) == at(row, column+1));
	}
	return ret;
}

bool Grid::isLost()
{
	for (int i = 1; i <= 4; ++i)
	{
		for (int j = 1; j <= 4; ++j)
		{
			if (!at(i, j))
				return false;
			else
			{
				if (isExistEqual(i, j))
					return false;
			}
		}
	}

	return true;
}

//下
bool Grid::moveDown()
{
	int top = 1, bottom = 4;
	bool moved = false;

	for (int column = 1; column <= 4; ++column)
	{
		//相同的数字合并
		int last = 0, pos = 0;
		for (int work = bottom; work >= top; --work)
		{
			if (at(work, column))
			{
				if (last)
					if (at(work, column) == last)
					{
						at(work, column) = 0;
						at(pos, column) *= 2;
						moved = true;
						last = 0;
						pos = 0;
					}
					else
					{
						last = at(work, column);
						pos = work;
					}
				else if (!last)
				{
					last = at(work, column);
					pos = work;
				}
			}
		}

		//将数字往栈底挤
		for (int work = bottom; work >= top; --work)
		{
			if (at(work, column))
			{
				for (int i = work; i <= bottom-1; ++i)
				{
					if (!at(i+1, column))
					{
						swap(at(i, column), at(i+1, column));
						moved = true;
					}
					else break;
				}
			}
		}
	}

	return moved;
}

//上
bool Grid::moveUp()
{
	int top = 4, bottom = 1;
	bool moved = false;

	for (int column = 1; column <= 4; ++column)
	{
		//相同的数字合并
		int last = 0, pos = 0;
		for (int work = bottom; work <= top; ++work)
		{
			if (at(work, column))
			{
				if (last)
					if (at(work, column) == last)
					{
						at(work, column) = 0;
						at(pos, column) *= 2;
						moved = true;
						last = 0;
						pos = 0;
					}
					else
					{
						last = at(work, column);
						pos = work;
					}
				else if (!last)
				{
					last = at(work, column);
					pos = work;
				}
			}
		}

		//将数字往底挤
		for (int work = bottom; work <= top; ++work)
		{
			if (at(work, column))
			{
				for (int i = work; i >= bottom+1; --i)
				{
					if (!at(i-1, column))
					{
						swap(at(i, column), at(i-1, column));
						moved = true;
					}
					else break;
				}
			}
		}
	}

	return moved;
}

//左
bool Grid::moveLeft()
{
	int top = 4, bottom = 1;
	bool moved = false;

	for (int row = 1; row <= 4; ++row)
	{
		//相同的数字合并
		int last = 0, pos = 0;
		for (int work = bottom; work <= top; ++work)
		{
			if (at(row, work))
			{
				if (last)
					if (at(row, work) == last)
					{
						at(row, work) = 0;
						at(row,pos) *= 2;
						moved = true;
						last = 0;
						pos = 0;
					}
					else
					{
						last = at(row, work);
						pos = work;
					}
				else if (!last)
				{
					last = at(row, work);
					pos = work;
				}
			}
		}

		//将数字往底挤
		for (int work = bottom; work <= top; ++work)
		{
			if (at(row, work))
			{
				for (int i = work; i >= bottom+1; --i)
				{
					if (!at(row, i-1))
					{
						swap(at(row, i), at(row, i-1));
						moved = true;
					}
					else break;
				}
			}
		}
	}

	return moved;
}

//右
bool Grid::moveRight()
{
	int top = 1, bottom = 4;
	bool moved = false;

	for (int row = 1; row <= 4; ++row)
	{
		//相同的数字合并
		int last = 0, pos = 0;
		for (int work = bottom; work >= top; --work)
		{
			if (at(row, work))
			{
				if (last)
					if (at(row, work) == last)
					{
						at(row, work) = 0;
						at(row,pos) *= 2;
						moved = true;
						last = 0;
						pos = 0;
					}
					else
					{
						last = at(row, work);
						pos = work;
					}
				else if (!last)
				{
					last = at(row, work);
					pos = work;
				}
			}
		}

		//将数字往底挤
		for (int work = bottom; work >= top; --work)
		{
			if (at(row, work))
			{
				for (int i = work; i <= bottom-1; ++i)
				{
					if (!at(row, i+1))
					{
						swap(at(row, i), at(row, i+1));
						moved = true;
					}
					else break;
				}
			}
		}
	}

	return moved;
}

main.cpp

/***************************************************************
 *程序名称:2048
 *内容摘要:练习
 *其它说明:无
 *当前版本:V1.0
 *作    者:tbz
 *完成日期:2014年5月8日
 ***************************************************************/

#include <cstdlib>
#include <conio.h>
#include "Grid.h"
#include <iostream>
using namespace std;

bool isNeed(char c)
{
	switch (c)
	{
		case ‘a‘:case ‘s‘:case ‘d‘:case ‘w‘:
		case ‘A‘:case ‘S‘:case ‘D‘:case ‘W‘:
			return true;
	}
	return false;
}

int main(int argc, char const *argv[])
{
	Grid game;

	//game flow control
	while (true)
	{
		system("cls");
		game.print();
		if (game.isWon())
		{
			cout << endl << "Congratulation!	You won!" << endl;
			cout << "Press any key to exit." << endl;
			getch();
			return 0;
		}

		if (game.isLost())
			break;

		//Promt
		cout << endl;
		cout << "A -> Left, D -> Right, W -> Up, S -> Down. (K -> Exit)" << endl;
		char input = getch();

		if (input == ‘k‘)
			return 0;
		if (!isNeed(input))	continue;

		game.move(input);
	}

	cout << "Sorry! You lose." << endl;
	getch();
	return 0;
}

总结:

分析很重要。

每开发一个独立功能,就测试一下,可减少后期调试的痛苦。

[Practice]山寨2048之Terminal版

时间: 2024-10-14 06:34:12

[Practice]山寨2048之Terminal版的相关文章

cocos2dx3.0 2048多功能版

1.2048项目描述 1.1.2048功能描述 实现手机上2048的功能,同时具备可以删除任意一个方块的功能,悔棋功能,退出自动保存,启动自动加载功能. 1.2.2048所需技术 UserDefult保存文件,棋盘信息保存,消除的核心算法 2.2048运行流程 3.2048详细设计 3.1方块类 游戏的是由4*4个方块构成的游戏,首先每个可移动块都是一个实体,受方块管理器统一管理它们的动作(移动,消失). class CSquare :public Node { public: CSquare(

[Python]简易terminal歌词滚动播放器

整合了网易云的一些API,想写一个terminal版的音乐播放器,但是还没有想好写成什么样子. 暂时写了一个必须又的功能:带歌词滚动的播放器,用了pygame里的mixer来播放音乐. 准备有时间的时候实现一下其他的功能. 1 # -*- coding:utf-8 -*- 2 import re 3 import os 4 import time 5 import copy 6 import threading 7 import pygame 8 from pygame import mixer

我也来开发2048之确定思路

以下内容拔自百度: 2048是比較流行的一款数字游戏.原版2048首先在github上公布,原作者是Gabriele Cirulli.它是基于<1024>和<小3传奇>的玩法开发 而成的新型数字游戏.随后2048便出现各种版本号,走各大平台.由Ketchapp公司移植到IOS的版本号最为火热,如今约有1000万下载,其名字跟 原版一模一样.衍生版中最出名的是<2048六边形>版本号,先后在全球81个国家中的board game中排进了前200.安卓版非常火爆的有<

微信公众平台开发(100) 2048游戏

微信开发第100篇了,算上微信支付和微信小店,其实已经超过了,这次完整讲一下2048游戏吧. 一.2048游戏 <2048>是比较流行的一款数字游戏.原版2048首先在github上发布,原作者是Gabriele Cirulli.它是基于<1024>和<小3传奇>的玩法开发而成的新型数字游戏 .随后2048便出现各种版本,走各大平台.由Ketchapp公司移植到IOS的版本最为火热,现在约有1000万下载,其名字跟原版一模一样.衍生版中最出名的是<2048六边形&

还有多少人在玩2048现在都4096了

<2048>是比较流行的一款数字游戏.原版2048首先在github上发布,原作者是Gabriele Cirulli.它是基于<1024>和<小3传奇>的玩法开发而成的新型数字游戏[1] .随后2048便出现各种版本,走各大平台.由Ketchapp公司移植到IOS的版本最为火热,现在约有1000万下载,其名字跟原版一模一样.衍生版中最出名的是<2048六边形>版本, 先后在全球81个国家中的board game中排进了前200. 安卓版非常火爆的有<挑

用 CentOS 7 打造合适的科研环境

这篇博文记录了我用 CentOS 7 搭建 地震学科研环境 的过程,供我个人在未来重装系统时参考.对于其他地震学科研人员,也许有借鉴意义. 阅读须知: 本文适用于个人电脑,不适用于服务器: 不推荐刚接触 Linux 的人使用 CentOS 发行版: 本文尽量写的浅显易懂,但要求读者掌握 Linux 基础知识: 本文所有操作均在 CentOS 7 下完成,其他发行版或多或少与 CentOS 7 不同,因而仅供参考: 本文所安装的软件纯粹出于个人习惯及喜好,读者应自己判断,按需安装: 安装 Cent

用CentOS 7打造合适的科研环境 :zhuan

这篇博文记录了我用CentOS 7搭建地震学科研环境的过程,供我个人在未来重装系统时参考.对于其他地震学科研人员,也许有借鉴意义. 阅读须知: 本文适用于个人电脑,不适用于服务器: 不推荐刚接触Linux的人使用CentOS发行版: 本文尽量写的浅显易懂,但要求读者掌握Linux基础知识: 本文所有操作均在CentOS 7下完成,其他发行版或多或少与CentOS 7不同,因而仅供参考: 本文所安装的软件纯粹出于个人习惯及喜好,读者应自己判断,按需安装: 安装CentOS CentOS 7的安装与

用CentOS 7打造合适的科研环境

http://seisman.info/linux-environment-for-seismology-research.html 这篇博文记录了我用CentOS 7搭建地震学科研环境的过程,供我个人在未来重装系统时参考.对于其他地震学科研人员,也许有借鉴意义. 阅读须知: 本文适用于个人电脑,不适用于服务器: 不推荐刚接触Linux的人使用CentOS发行版: 本文尽量写的浅显易懂,但要求读者掌握Linux基础知识: 本文所有操作均在CentOS 7下完成,其他发行版或多或少与CentOS 

Linux系统之路——用CentOS 7打造合适的科研环境

安装CentOS CentOS 7的安装与其他Linux发行版的安装差不多,个别地方稍有不同. 准备工作 准备材料 U盘:容量700M以上,用于制作U盘启动盘,因为在制作启动盘时会格式化U盘,所以U盘内不要包含重要资料 CentOS 7.1 LiveCD ISO镜像文件 Universal USB installer:Windows下的U盘启动盘制作工具 一个已安装Windows的电脑:用于制作U盘启动盘 运行Universal USB installer并制作U盘启动盘 将U盘插入计算机,重启