GithubHelp home page GithubHelp logo

connect4ai's Introduction

Connect 4 game AI

This project is about building a bot for connect 4 game using Java, and it follows the requirements and restrictions described by a platform called riddles.io.

First approach

The first approach to this project was using a char[][] which represents the game board. It would probably be the simplest solution when most people first think of the solution. The bot uses depth-first search algorithm to calculate what would happen at the end of each move, and makes the best move.

An update on the board is given by a String which represents the whole board. Rather than reading the whole String to see which position has been updated, I used an int[] to store current levels of each column in the board. By only storing potential positions to be updated, the handler can only check specific characters in the String. After updating the board, the bot uses depth-first search and finds the next move it should make.

This approach simply works when there are enough resources to handle this algorithm. In reality, this approach is very costly because everytime we recursively call the dfs method, cases we have to check multiplies. In early searches, it mostly multiplies by 7, and it also redundantly checks cases which have been searched before.

Second approach

After researching online, I found some good ways to improve the performance. I found out bit manipulation could optimize the algorithm, and using a BitSet to store the board information was an option. By manipulating bits, it could check vertical, horizontal, and 2 diagonal moves more efficiently everytime we calculate how good a move is. But, I realized it would be more efficient to use a long to keep track of the board. It is more lightweight and quicker since it is a primitive data type. The board shape of connect 4 game will unlikely to be changed in near future, and long, which has 64 bits, is good enough to store 42 positions(6*7) in the board. Each bit in the long represents a specific position in the board and it can assess the information we need by manipulating bits.

To avoid checking cases redundantly, I utilized dynamic programming by implementing a transposition table to memorize cases that have been searched before. So when a case has been searched before, we can just use the value that has been already calculated. In addition to the transposition table, I used alpha-beta pruning algorithm which is commonly used for two-player games.

Despite efforts to improve the performance, it still did not satisfied the time limit specified by the platform. It had exponentially more cases to check in ealier than later, so I came up with a simple trick.

Third approach

When you start connect 4 game, it is always better to place your discs in the middle because it gives us the most opportunities. Actually, if you start the game with the middle column and play perfectly, you can always win. So, even though the computer may search all moves, it will end up with choosing the middle column for the first move. And when the computer finds out the best move, it means it searched all 4,531,985,219,092 possible positions when the first request is made. If we just hard code the first move, then we can decrease the number of positions to be explored to 1/7 of that massive number. Actually, optimal moves in early connect 4 game are quite simple, and we can help the bot dramatically by providing early moves.

We can dramatically decrease the number of moves which need to be searched, and it can dramatically increase the space for storing moves after first. So it needs some balance between space vs. time and optimization of hard-coded early moves. Also, when we use int which has 32 bits, it can only safely store 9 moves assuming we store our moves and enemy moves(Integer.MAX_VALUE starts with 2, and it has a high chance of making it negative when we update 10th move). Rather than storing both sides' moves, we can only store the enemy's move because we will always choose the same move given an enemy move. More specifically, we need to consider maximum 7 moves by the emeny, but when once the enemy makes a move, our move is always determined. So we can assume that the next move made by enemy is always based on the specifically determined move we previously made. But, One confusion can occur. If we only keep track of the enemy move, how do we know if we made a move before sequence "3"? We start with column 3, and it could be either "we made the first move, and the enemy made a move which is 3" or "the game is just started and the enemy made a move which is 3". To avoid this confusion, I just put a number indicating whether the bot started first. Then how do we differentiate it from column? It's easy! I used number 8 and 9 which cannot be a column given 7 column board.

Conclusion

Overall, it was a fun challenge. I could get many good resources online to optimize the bot, and it was very nice to learn and build. Balancing between optimization and scalability, I had to time methods and implementations. I would say there are still more ways to optimize my implementation, and it was fun to apply new algorithms. There are more topics and decisions that I did not specifically share here, and I am willing to share if anyone wants to talk with me. Please let me know if you want to talk.

connect4ai's People

Contributors

sunho0301 avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.