2048 AI
A couple of weeks ago, one intern of my team re-posted a game called 2048 into our wechat group. Soon we found we could not stop playing the game. And some of us started to post screenshots of scores we got in the game. We made higher and higher scores and finally completed 2048 tiles one day later. But we didn’t stop, we kept going and tried to accomplish even bigger tile than 2048.
So I thought about one question:
What is the biggest tile that can be made in the game?
We know that two 2s can be merged to make a 4, and two 4s can be merged to make an 8. And eventually, any big tile is made out of basic tiles, i.e. 2s or 4s. And after reading a little bit of code of the game, I found that the basic tiles appearing on the board have 90% probability to be a 2 and 10% to be a 4.
Let’s ignore 4s first. We assume all new tiles are 2s. So any big tile is made from a set of 2s, via a sequence of merges. E.g. a 16 is made out of eight 2s via 7 merges. I drew a tree to illustrate these merges for the 16:
The two 2s, tile A and tile B, happen to be the LAST pair of 2s merged in the game. We can always find such a pair of 2s in any tree for a 16 or other big tiles.
Consider the moment that tile A is merged(with B). There is a path from A to the root R: A->C->F->R. All tiles in the path except A don’t exist at that moment. So, look at those tiles going to be merged with a tile in the path, i.e. the brothers of tiles in the path: tile B, D and E. Each of them either exists on the board, or will be made from some tiles existing on the board, because all 2s in the tree except A and B have already been merged and new 2s coming out later will not be used to make the 16. In both cases, there is at least one tile existing on the board for each of these brothers.
Now we can calculate the number of tiles on the board at that moment: A, B, D or its component tiles, and E or its comonent tiles. There are at least 4 tiles. It equals to the length of the path from A to the root! Yes, generally, to make a 2^N, the number of tiles on the board when the last two 2s are going to be merged is at least N – the height of the ‘merge’ tree for 2^N.
So the 2048 game has exactly 16 slots and can not make a 2^17 in any way.
Back to the original 2048 game, a basic tile has 10% possibility to be 4. With some similar analysis, we can know that the game can not make a 2^18 even even if all basic tiles coming out are 4s.
Knowing the biggest possible tile in the game won’t help me play the game better. So I tried to implement a program to run the game for me.
Implement a 2048 AI with Javascript
I first wrote a C++ AI program for the game. Since it’s almost impossible to make a 2^16, I encoded a tile in 4 bit and encoded the whole board in a 64bit integer. So I could use bitwise operations to simulate movements easily. But a C++ program can not run in browser. And it’s not cool if it can not be put onto the web. So I rewrote it with javascript.
I had not written any javascript code to solve such a problem requiring so much computing. I had planed to search at least 10 steps and use some kind of cache map to avoid duplicated computing. But unfortunately I found javascript is far slower than C++. So I decided to only search 3 steps in most cases so that I can keep the amount of computing in a reasonable range.
I used javascript objects as maps to cache searching results and avoid duplicated computing before. But later I found it actually hurt the performance. I removed all of these code and made the program run twice as fast as before.
After some optimizations, I finally made the AI program run pretty fast. On the chrome browser in my laptop, it usually spends less than 30 seconds to make a 2048. And it hardly fails to make a 2048 and often successfully makes a 4096 or 8192. And I have even made a 16384!

The AI algorithm
The code has is quite short. The basic idea is to find the direction for each movement on which the game can get the maximal expected score. It’s expected score because a new tile can appear at any empty slot with the same possibility, and has 90% chance to be 2 and 10% to be 4.
The algorithm is:
Estimate() is to estimate the state after max_step movements. I tried a couple of functions and found a pretty good function. In the function, the estimation score will be punished by the differences of adjacent tiles. So states with high estimation scores usually put the biggest tile at one of the four corners because the number of adjacent tiles is mimimum if at corner, and put other big tiles at the edge of the board and adjacent to a bigger tile.
I use a very large penalty(-10^20) for a dead state. So the program will try its best to avoid dead states. Although it maybe over evaluates dead states, I want the program to avoid the risk of failing before making a 2048.
By default, the max_step is 3. If when a search ends the number of visited states is less than 10000, it will start a new search with max_step increased by 1. So the program will keep searching more and more deeply until the number of visited states is larger than 10000. Usually there are much fewer states can be reached in a bad situation than a good situation. The strategy can make sure the program does enough searchs when the game goes bad and doesn’t waste too much time when the game goes well. There are indeed some duplicated computing to start a completely new search. But since the number of visited states increases approximately exponentially with the depth, only a small portion of computing is duplicated.
In the end, I posted a 70,000+ and later a 170,000+ in the group and successfully extinguished others’ passions on the game:)
Name already in use
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
A game of 2048 in vanilla JavaScript, HTML and CSS
In this walkthrough, we make the very popular game 2048 in JavaScript, HTML and CSS! No canvas required! (Now with more accurate subtitles for programmers)
Full video walkthrough here
2048 is played on a 4×4 grid, with numbered tiles that slide smoothly when a player moves them using the four arrow keys. Each time you slide, a new tile will randomly appear in an empty spot on the board. Tiles slide as far as possible in the chosen direction until they are stopped by either another tile or the edge of the grid. If two tiles of the same number collide while moving, they will merge into a tile with the total value of the two tiles that collided. The resulting tile cannot merge with another tile again in the same move.
Tools and Software I used in this video:
- TabNine By Codota: https://bit.ly/Codota
- VSCode: https://bit.ly/VSCode-Editor
By creating this popular game we will learn the following javaScript Methods:
- querySelector()
- getElementById()
- createElement()
- appendChild()
- push()
- Math.floor()
- Math.random()
- length
- innerHTML
- parseInt()
- filter()
- Array()
- fill()
- concat()
- keyCode
- addEventListener()
- removeEventListener()
- setTimeout()
- clearInterval()
- setInterval()
If you did like this video, please do Like and Subscribe so I know to make others like this!
I would love to see what you have made so please do share your finished games with me on twitter! My handle is @ania_kubow.
Copyright (c) 2020 Ania Kubow
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the «Software»), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*Translation: Ofcourse you can use this for you project! Just make sure to say where you got this from 🙂
THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Русские Блоги
Ниже представлена мини-игра 2048 года, которую я написал на js на этапе изучения предыдущей технологии на js. Конкретный код и введение следующие:
Во-первых, мы должны создать игровой интерфейс с помощью HTML на странице, создать сетку из девяти квадратов 4×4 и добавить табло для накопленных результатов.
Эффект страницы следующий:
Код HTML выглядит следующим образом:
Код CSS выглядит следующим образом:
Код JS выглядит следующим образом:

Интеллектуальная рекомендация
Реализация JavaScript Hashtable
причина Недавно я смотрю на «Структуру данных и алгоритм — JavaScript», затем перейдите в NPMJS.ORG для поиска, я хочу найти подходящую ссылку на библиотеку и записывать его, я могу исполь.
MySQL общие операции
jdbc Транзакция: транзакция, truncate SQL заявление Transaction 100 000 хранимая процедура mysql msyql> -определить новый терминатор,Пробелов нет mysql>delimiter // mysql> -создание хранимой .
Используйте Ansible для установки и развертывания TiDB
жизненный опыт TiDB — это распределенная база данных. Настраивать и устанавливать службы на нескольких узлах по отдельности довольно сложно. Чтобы упростить работу и облегчить управление, рекомендуетс.
Последняя версия в 2019 году: использование nvm под Windows для переключения между несколькими версиями Node.js.
С использованием различных интерфейсных сред вы можете переключаться между разными версиями в любое время для разработки. Например, развитие 2018 года основано наNode.js 7x версия разработана. Тебе эт.
![]()
Шаблон проектирования — Создать тип — Заводской шаблон
Заводская модель фабрикиPattern Решать проблему: Решен вопрос, какой интерфейс использовать принципСоздайте интерфейс объекта, класс фабрики которого реализуется его подклассом, чтобы процесс создания.
Author’s brief introduction
CSDN blog expert, engaged in software development for many years, proficient in Java, JavaScript, the blogger is also from scratch to learn and grow step by step, know the importance of learning and accumulation, like to fight with the majority of ADC upgrade, welcome your attention, look forward to learning, growth and take off with you!
rendering
Implementation approach
- Write page and canvas code.
- Draw the background.
- Draw all the cards.
- Generate a card (2 or 4) at random.
- Keyboard events listening (up, down, left, right — click listening).
- According to the direction of the keyboard, process the number movement merge.
- Add success and failure determination.
- Handle other finishing touches.
Code implementation
Writing page code
Add the canvas
Write the code in 2048.js
- Create a function
- Initialize and draw background code (written in 2048.js)
- Add the following JS code to the page code
Draw all the cards
- Create a Card
- Create a card
- Call draw code
Operation effect: 4. Change the default number on the card
Generate a card at random, 2 or 4
- Let’s set num to 0 by default
- Because the ratio of 2 and 4 is 1:4, the number 1-5 is chosen randomly. When it is 1, it means that the number 2 will appear when it is 2, 3, 4 and 5.
- If you randomly get I, j, you get the position of the card, you cutover I, j gets the card instance, if there’s no number on the card, it’s ok, otherwise you recursively continue to get it until you get it.
- I’m just going to take the number that I just picked up and put it in my Card instance object.
The code is as follows:
Called in the draw method to open the game with a default number Operation effect:
Add keyboard events
Also called in the draw method
- Add movement logic processing code
- Add up, down, left, and right processing logic
- Add upward-moving processing logic to Card
- Move from line 2, because you don’t need to move the first line.
- As long as the number on the card is not 0, it means to move.
- According to i-1, I get the last card, and if the last card is empty, I swap the current card, and recurse, because I might have to move up.
- If the current card has the same number as the previous card, it is merged.
- If neither of the preceding two types is displayed, no operation is performed.
- Add code for the other three directions to Card
This is basically the end of the game, add other ancillary things, such as restart, game win, game end, etc., but not to mention.
See the big guy here, move the rich little hands dot praise + reply, can [concern] a wave of better.