Skip to content

Connect 4 game on both the Angular5 and the Vue2 frameworks.

Notifications You must be signed in to change notification settings

duggthangs/connect4

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Connect Four - game

This is a simple working example of the popular game Connect Four. It is a 2 player game where the goal is to form a horizontal, diagonal, or vertical line of four of one's own discs.

I have two identical versions in both the VueJs 2 and Angular5 frameworks.

How it works

  1. Enter names for Player 1 and Player 2.
  2. Press the play button.
  3. Click on the column of the top row with the arrow icon to drop your chip.
  4. Keep repeating step 3, alternating between players until you get 4 in a row either in diagonal, horizontal, or vertical positions.
  5. Once a winner has been made, a dialog box will appear asking you to play again.
    • Press OK to clear the board.
    • Press Cancel to go back to the home page.

Components

Components remain consistent with both frameworks, the only difference is the associated HTML and CSS files. In Vue, the HTML and CSS are all together in one .vue file, while in Angular they are separated, but remain in the same component folder.

App

The App component is responsible for holding the logo and the "true/false" state of the Start and Table components.

Start

The Start component is responsible for collecting the names of Player 1 and Player 2.

Peg

The Peg component is the actual chip that retrieves the prop, "color", to initialize with the color "red" or "black".

Table

The Table component is responsible for creating the actual board/table of the game. It also shows the player name with the color of chip for each player and who's turn it is. Within this component, there are two buttons, one to reset the board and the other to navigate back to the Start component.

Win Condition

The naive approach to check for a win condition is to scan the entire row, column, diagonal left and diagonal right every time a chip is dropped. That is a-lot of iteration and can slow down your application, especially if you add more rows and columns.

The way this application works is similar to how a Linked List works. Every cell is created with an object holding a pointer to the adjacent cells around it and the value of which player it belongs to.

An empty cell is represented with the player value NULL, and if the position is pointing outside of the table then the pointer itself is set to NULL

createTable() {
	let table = [];
	let totalRows = 6;
	let totalCols = 7;
	for (let row = 0; row < totalRows; row++) {
		table.push([]);
		for (let col = 0; col < totalCols; col++) {
			table[row].push({})
		}
	}
	for (let row = 0; row < totalRows; row++) {
		for (let col = 0; col < totalCols; col++) {
			table[row][col].left = col > 0 ? table[row][col - 1] : null;
			table[row][col].right = col < totalCols - 1 ? table[row][col + 1] : null;
			table[row][col].bottom = row < totalRows - 1 ? table[row + 1][col] : null;
			table[row][col].top = row > 0 ? table[row - 1][col] : null;
			table[row][col].topLeft = row > 0 && col > 0 ? table[row - 1][col - 1] : null;
			table[row][col].topRight = row > 0 && col < totalCols - 1 ? table[row - 1][col + 1] : null;
			table[row][col].bottomLeft = row < totalRows - 1 && col > 0 ? table[row + 1][col - 1] : null;
			table[row][col].bottomRight = row < totalRows - 1 && col < totalCols - 1 ? table[row + 1][col + 1] : null;
			table[row][col].player = null;
		}
	}
	return table
}

Once the current player chip is detected on, for example, Left, then it keeps going in that direction, keeping count the number of times it matches the current player value until it reaches NULL or if player value does not match.

Condition Expression: currentCell.left == null or currentCell.left.player != currentCell.player

If condition expression is met then it goes back to the first cell where the initial win condition is checked and goes the opposite direction in this case right. Once the condition expression in the opposite direction is met, it checks the count and if count < 4 returns false, failing the win condition. If count > 3 returns true, evaluating a win for the player.

checkWin(player, cell) {
	let count = 0;
	if (it(player, cell, 'left', 'right')) {
		return true
	}
	if (it(player, cell, 'top', 'bottom')) {
		return true
	}
	if (it(player, cell, 'topLeft', 'bottomRight')) {
		return true
	}
	if (it(player, cell, 'topRight', 'bottomLeft')) {
		return true
	}
	// Evalutes win as false and switches player
	this.nextPlayer();

	function it(p, c, pos, opPos) {
		if (count === 4) {
			return true
		}
		if (!c || !c.player || c.player.name !== p) {
			if (opPos === null) {
				count = 0;
				return false
			}
			return it(p, cell[opPos], opPos, null)
		} else {
			count++;
			return it(p, c[pos], pos, opPos)
		}
	}
},

Conclusion

This way of checking for win condition is very efficient and does not care whether there are 1,000 or 1,000,000 rows and columns.

About

Connect 4 game on both the Angular5 and the Vue2 frameworks.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published