I am trying to create a bingo game.
It's an assignment that was given to us. I wrote all the functions I need however the "main" function which runs the entire thing, it has a loop which doesn't stop.
I don't seem to know what makes it infinite since I gave a condition for it to stop at the end.
The code is a bit long. I hope you can help me out.
var gNums = []
var gPlayers = [
{
name: 'player1',
hitCounts: 0,
board: creatBingoBoard()
},
{
name: 'player2',
hitCounts: 0,
board: creatBingoBoard()
}
]
// var check=gPlayers[0].board[0][0].isHit = true
// console.table(printBingoBoard(gPlayers[0].board))
// console.table(printBingoBoard(gPlayers[1].board))
// var check = gPlayers[0].board[0][0].isHit = true
playBingo()
// console.table(gPlayers[0].board)
function playBingo() {
// debugger
resetNums()
var isVictory = false
while (!isVictory) {
// console.log('still running!')
var calledNum = drawNum(gNums)
// console.log(calledNum)
for (var i = 0; !isVictory && i < gPlayers.length; i++) {
var player = gPlayers[i]
markBoard(player, calledNum)
isVictory = checkBingo(player)
}
}
}
function creatBingoBoard() {
resetNums()
var board = [];
const SIZE = 5;
for (var i = 0; i < SIZE; i++) {
board[i] = [];
for (var j = 0; j < SIZE; j++) {
board[i][j] = {
value: getRandomIntInclusive(0, 25),
isHit: false
}
}
}
return board;
}
function printBingoBoard(board) {
var bingoBoardCopy = []
var size = board.length
for (var i = 0; i < size; i++) {
bingoBoardCopy[i] = []
for (var j = 0; j < size; j++) {
if (board[i][j].isHit === true) {
bingoBoardCopy[i][j] = board[i][j].value + 'v'
} else bingoBoardCopy[i][j] = board[i][j].value
}
}
return bingoBoardCopy
}
function resetNums() {
gNums = []
for (var i = 0; i < 25; i++) {
gNums.push(i)
}
return gNums
}
function drawNum(nums) {
var index = getRandomIntInclusive(0, nums.length);
var num = nums[index];
nums.splice(index, 1);
return num;
}
function markBoard(player, calledNum) {
for (var i = 0; i < player.board.length; i++) {
for (var j = 0; j < player.board.length; j++) {
var cell = player.board[i][j]
if (cell === calledNum) {
player.hitCounts++
cell.isHit = true
}
}
}
printBingoBoard(player.board)
}
function checkBingo(player) {
// for (var i = 0; i < player.length; i++) {
// if (player.hitsCount === 25) return true
if (player.hitCounts === 25) {
return true
}
return false;
}
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive
}
In markBoard, you check the value of player.board[i][j]. That's an object, yet you're comparing it to a number. The numeric value you're after appears to be player.board[i][j].value.
As others have stated in the comments, the best way to approach this type of problem is to use a debugger. Chrome Developer Tools allows you to attach breakpoints and inspect the value of your objects in code. However, logging the values of your variables is also a good debugging tool.
Got it to work!
I tried not to mess with your code too much.
My changes are marked with // <- fix.
Just showing who's the winner :)
You never pushed 25.
Off-by-one.
You were comparing the drawn number with the cell, instead of the cell's value.
var gNums = []
var gPlayers = [
{
name: 'player1',
hitCounts: 0,
board: creatBingoBoard()
},
{
name: 'player2',
hitCounts: 0,
board: creatBingoBoard()
}
]
// var check=gPlayers[0].board[0][0].isHit = true
// console.table(printBingoBoard(gPlayers[0].board))
// console.table(printBingoBoard(gPlayers[1].board))
// var check = gPlayers[0].board[0][0].isHit = true
playBingo()
// console.table(gPlayers[0].board)
function playBingo() {
// debugger
resetNums()
var isVictory = false
let totalNumbersCalled = 0;
while (!isVictory) {
var calledNum = drawNum(gNums)
console.log(++totalNumbersCalled, '->', calledNum);
for (var i = 0; !isVictory && i < gPlayers.length; i++) {
var player = gPlayers[i]
markBoard(player, calledNum)
isVictory = checkBingo(player)
}
}
console.log('Player', i - 1, 'wins!'); // <- fix 1
}
function creatBingoBoard() {
resetNums()
var board = [];
const SIZE = 5;
for (var i = 0; i < SIZE; i++) {
board[i] = [];
for (var j = 0; j < SIZE; j++) {
board[i][j] = {
value: getRandomIntInclusive(0, 25),
isHit: false
}
}
}
return board;
}
function printBingoBoard(board) {
var bingoBoardCopy = []
var size = board.length
for (var i = 0; i < size; i++) {
bingoBoardCopy[i] = []
for (var j = 0; j < size; j++) {
if (board[i][j].isHit === true) {
bingoBoardCopy[i][j] = board[i][j].value + 'v'
} else bingoBoardCopy[i][j] = board[i][j].value
}
}
return bingoBoardCopy
}
function resetNums() {
gNums = []
for (var i = 0; i <= 25; i++) { // <- fix 2
gNums.push(i)
}
return gNums
}
function drawNum(nums) {
var index = getRandomIntInclusive(0, nums.length - 1); // <- fix 3
var num = nums[index];
nums.splice(index, 1);
return num;
;
}
function markBoard(player, calledNum) {
for (var i = 0; i < player.board.length; i++) {
for (var j = 0; j < player.board.length; j++) {
var cell = player.board[i][j]
if (cell.value === calledNum) { // <- fix 4
player.hitCounts++
cell.isHit = true
}
}
}
printBingoBoard(player.board)
}
function checkBingo(player) {
// for (var i = 0; i < player.length; i++) {
// if (player.hitsCount === 25) return true
if (player.hitCounts === 25) {
return true
}
return false;
}
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
//The maximum is inclusive and the minimum is inclusive
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var gNums = []
var gPlayers = [
{
name: 'player1',
hitCounts: 0,
board: creatBingoBoard()
},
{
name: 'player2',
hitCounts: 0,
board: creatBingoBoard()
}
]
// var check=gPlayers[0].board[0][0].isHit = true
console.table(printBingoBoard(gPlayers[0].board))
console.table(printBingoBoard(gPlayers[1].board))
// var check = gPlayers[0].board[0][0].isHit = true
playBingo()
// console.table(gPlayers[0].board)
function playBingo() {
// debugger
resetNums()
var isVictory = false
while (!isVictory) {
// console.log('still running!')
var calledNum = drawNum();
//<-- Fix 1 for some reason callednum is coming as Undefined
if(calledNum){
// console.log(calledNum)
for (var i = 0; !isVictory && i < gPlayers.length; i++) {
var player = gPlayers[i]
markBoard(player, calledNum)
isVictory = checkBingo(player)
}
}
//<-- Fix 2 I am stopping fo gNums is empty
if(gNums.length == 0) isVictory=true;
}
console.table(printBingoBoard(gPlayers[0].board))
console.table(printBingoBoard(gPlayers[1].board))
}
function creatBingoBoard() {
resetNums()
var board = [];
const SIZE = 5;
for (var i = 0; i < SIZE; i++) {
board[i] = [];
for (var j = 0; j < SIZE; j++) {
board[i][j] = {
value: getRandomIntInclusive(0, 25),
isHit: false
}
}
}
return board;
}
function printBingoBoard(board) {
var bingoBoardCopy = []
var size = board.length
for (var i = 0; i < size; i++) {
bingoBoardCopy[i] = []
for (var j = 0; j < size; j++) {
if (board[i][j].isHit === true) {
bingoBoardCopy[i][j] = board[i][j].value + 'v'
} else bingoBoardCopy[i][j] = board[i][j].value
}
}
return bingoBoardCopy
}
function resetNums() {
gNums = []
for (var i = 0; i < 25; i++) {
gNums.push(i)
}
return gNums
}
function drawNum() {
var index = getRandomIntInclusive(0, gNums.length);
var num = gNums[index];
gNums.splice(index, 1);
return num;
}
function markBoard(player, calledNum) {
for (var i = 0; i < player.board.length; i++) {
for (var j = 0; j < player.board.length; j++) {
var cell = player.board[i][j]
//<-- Fix3 Cell is a object so we need to check with value
if (cell.value === calledNum) {
player.hitCounts++
cell.isHit = true
}
}
}
printBingoBoard(player.board)
}
function checkBingo(player) {
// for (var i = 0; i < player.length; i++) {
// if (player.hitsCount === 25) return true
if (player.hitCounts === 25) {
return true
}
return false;
}
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive
}
I'm trying to get the min and max value of a Dataview with the help of getColumnRange(). Unfortunately the values I get are not the ones I'd expect. Can someone advise me how I can get the correct values? The value I'd expect as max is 331M (the highest bar on the bar chart), but I get 8,5M. I tried to better my understanding of the DataView object with console.log(), however that didn't quite help me (line 65-71)
https://jsfiddle.net/zhp5rny6/3/
var data = new google.visualization.DataTable({
cols: [
{id:"","label":"Products","pattern":"","type":"string"},
{id:"","label":"Manila","pattern":"","type":"number"},
{id:"","label":"Bangkok","pattern":"","type":"number"},
{id:"","label":"New York","pattern":"","type":"number"},
{id:"","label":"Sydney","pattern":"","type":"number"}],
rows:[
{c:[{v:"Glasses"},{v:-1270.7287},{v:-4486.0961},{v:-1019.4662},{v:3763827.8335}]},
{c:[{v:"Joysticks"},{v:145543.985},{v:2108039.5802},{v:266392.5277},{v:6006566.18690001}]},
{c:[{v:"Laptops"},{v:1723781.2686},{v:4435404.56789999},{v:7060065.3164},{v:17514581.1763}]},
{c:[{v:"PS4"},{v:78002243.0557997},{v:47591320.6768999},{v:43832560.9528002},{v:161580254.021496}]},
{c:[{v:"XBOX One"},{v:10507117.0145001},{v:8059953.41120002},{v:14103816.4604002},{v:34676509.4036004}]},
{c:[{v:"Smartphones"},{v:2373067.7893},{v:-53954.2187},{v:30783391.8722},{v:37288122.5537999}]},
{c:[{v:"Chairs"},{v:86583.2876},{v:71082.0195},{v:79813.2918},{v:22959813.0499999}]},
{c:[{v:"CPU"},{v:12479599.4709999},{v:22650137.9890997},{v:17562381.7794999},{v:25589299.8099997}]},
{c:[{v:"RAM"},{v:null},{v:-59.1},{v:282.7517},{v:1461239.6186}]},
{c:[{v:"Table"},{v:-566.5377},{v:-217.3444},{v:-865.114},{v:356870.886599999}]},
{c:[{v:"Water"},{v:870883.521900001},{v:1128581.9856},{v:1177332.008},{v:3922057.50240001}]}]
});
var formatter = new google.visualization.NumberFormat({
pattern: 'short'
});
for (var i = 1; i < data.getNumberOfColumns(); i++) {
formatter.format(data, i);
}
var view = getDataView(data);
function getDataView(dataTable) {
var dataView;
var viewColumns = [];
for (var i = 0; i < dataTable.getNumberOfColumns(); i++) {
addViewColumn(i);
}
function addViewColumn(index) {
viewColumns.push(index);
if(index == (dataTable.getNumberOfColumns() - 1)) {
viewColumns.push({
calc: function (dt, row) {
for(var e = 0; e < dt.getNumberOfRows(); e++) {
var value = 0;
for(var u = 1; u < dt.getNumberOfColumns(); u++) {
value += dt.getValue(row, u);
}
return formatter.formatValue(value).toString();
}
},
type: 'string',
role: 'annotation',
});
}
}
dataView = new google.visualization.DataView(dataTable);
dataView.setColumns(viewColumns);
for(var z = 0; z < dataView.getNumberOfColumns(); z++) {
console.log(JSON.stringify(dataView.getColumnRange(z)));
}
console.log(JSON.stringify(dataView.getViewColumns()));
console.log(JSON.stringify(viewColumns));
return dataView;
}
the reason you get "8.5M" instead of "331M" is because the column type = 'string'
alphabetically, "8.5M" is greater than "331M"
to correct this issue, use a column type of 'number'.
when building the data view annotation column,
and return an object with both the value (v:) and formatted value (f:).
viewColumns.push({
calc: function (dt, row) {
for(var e = 0; e < dt.getNumberOfRows(); e++) {
var value = 0;
for(var u = 1; u < dt.getNumberOfColumns(); u++) {
value += dt.getValue(row, u);
}
return { // <-- return object here
v: value,
f: formatter.formatValue(value)
};
}
},
type: 'number', // <-- change to number
role: 'annotation',
});
see following working snippet...
google.charts.load("44", {packages:['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable({
cols: [
{id:"","label":"Products","pattern":"","type":"string"},
{id:"","label":"Manila","pattern":"","type":"number"},
{id:"","label":"Bangkok","pattern":"","type":"number"},
{id:"","label":"New York","pattern":"","type":"number"},
{id:"","label":"Sydney","pattern":"","type":"number"}],
rows:[
{c:[{v:"Glasses"},{v:-1270.7287},{v:-4486.0961},{v:-1019.4662},{v:3763827.8335}]},
{c:[{v:"Joysticks"},{v:145543.985},{v:2108039.5802},{v:266392.5277},{v:6006566.18690001}]},
{c:[{v:"Laptops"},{v:1723781.2686},{v:4435404.56789999},{v:7060065.3164},{v:17514581.1763}]},
{c:[{v:"PS4"},{v:78002243.0557997},{v:47591320.6768999},{v:43832560.9528002},{v:161580254.021496}]},
{c:[{v:"XBOX One"},{v:10507117.0145001},{v:8059953.41120002},{v:14103816.4604002},{v:34676509.4036004}]},
{c:[{v:"Smartphones"},{v:2373067.7893},{v:-53954.2187},{v:30783391.8722},{v:37288122.5537999}]},
{c:[{v:"Chairs"},{v:86583.2876},{v:71082.0195},{v:79813.2918},{v:22959813.0499999}]},
{c:[{v:"CPU"},{v:12479599.4709999},{v:22650137.9890997},{v:17562381.7794999},{v:25589299.8099997}]},
{c:[{v:"RAM"},{v:null},{v:-59.1},{v:282.7517},{v:1461239.6186}]},
{c:[{v:"Table"},{v:-566.5377},{v:-217.3444},{v:-865.114},{v:356870.886599999}]},
{c:[{v:"Water"},{v:870883.521900001},{v:1128581.9856},{v:1177332.008},{v:3922057.50240001}]}]
});
var formatter = new google.visualization.NumberFormat({
pattern: 'short'
});
for (var i = 1; i < data.getNumberOfColumns(); i++) {
formatter.format(data, i);
}
var view = getDataView(data);
function getDataView(dataTable) {
var dataView;
var viewColumns = [];
for (var i = 0; i < dataTable.getNumberOfColumns(); i++) {
addViewColumn(i);
}
function addViewColumn(index) {
viewColumns.push(index);
if(index == (dataTable.getNumberOfColumns() - 1)) {
viewColumns.push({
calc: function (dt, row) {
for(var e = 0; e < dt.getNumberOfRows(); e++) {
var value = 0;
for(var u = 1; u < dt.getNumberOfColumns(); u++) {
value += dt.getValue(row, u);
}
return {
v: value,
f: formatter.formatValue(value)
};
}
},
type: 'number',
role: 'annotation',
});
}
}
dataView = new google.visualization.DataView(dataTable);
dataView.setColumns(viewColumns);
for(var z = 0; z < dataView.getNumberOfColumns(); z++) {
console.log(JSON.stringify(dataView.getColumnRange(z)));
}
console.log(JSON.stringify(dataView.getViewColumns()));
console.log(JSON.stringify(viewColumns));
return dataView;
}
var options = {
annotations: {
alwaysOutside: true,
textStyle: {
fontSize: 10
}
},
height: 400,
isStacked: true
};
var chart = new google.visualization.ColumnChart(document.getElementById("columnchart_values"));
chart.draw(view, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="columnchart_values"></div>
I need to add a feature to Surface plots of Plotly. Feature is to change the range of Z axis data. problem is that it is only possible to limit the z axis value and expanding the values will not work. e.g. if I initialize 'Z Max' with 300 everything is fine but going back to 350 will keep the previous value. Although I have 'z_data' as my reference value that upon call of function by event listener should reserve the initially existing data, this does not happen and its values are updated to previously assigned 'Z Max' value.
Plotly.d3.csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv', function(err, rows){
function unpack(rows, key) {
return rows.map(function(row) { return row[key]; });
}
var z_data=[]
for(let i=0;i<24;i++) {
z_data.push(unpack(rows,i));
}
var allData = [];
for (let i=0; i<z_data.length; i++) {
for (let j=0; j<z_data[i].length; j++) {
allData.push(z_data[i][j])
}
}
var max = Math.max(...allData);
var min = Math.min(...allData);
setPlot(min, max);
function setPlot(zmin, zmax) {
console.log(z_data)
var newZData = z_data;
console.log('min specified: ' + zmin)
console.log('max specified: ' + zmax)
for (let i=0; i<newZData.length; i++) {
for (let j=0; j<newZData[i].length; j++) {
if (newZData[i][j] < zmin) {
newZData[i][j] = zmin
}
if (newZData[i][j] > zmax) {
newZData[i][j] = zmax
}
}
}
var data = [{
z: newZData,
type: 'surface'
}];
var layout = {
title: 'Mt Bruno Elevation',
autosize: false,
width: 500,
height: 500,
margin: {
l: 65,
r: 50,
b: 65,
t: 90,
}
};
Plotly.newPlot('myDiv', data, layout);
}
var zMin = document.querySelector("#zmin");
var zMax = document.querySelector("#zmax");
function updatePlot(){
setPlot(parseFloat(zMin.value), parseFloat(zMax.value));
}
zMin.addEventListener('change', updatePlot, false);
zMax.addEventListener('change', updatePlot, false);
Easier with JSFiddle:
http://jsfiddle.net/mwbbcyja/484/
I'm trying to create a chart that generates random numbers and it updates the maximum value after clicking on a button.
This is my controller:
$scope.max = 1;
$scope.randomNumber = function(max,min) {
var arr = [];
for (var i = 0; i < 60; i++) {
arr.push(Math.floor(Math.random()*(max-min+1)+min));
}
return arr;
}
$('#chart').highcharts({
series: [{
data: (function () {
var data = [];
for (var i = 0; i < 60; i++) {
data.push({
x: i,
y: $scope.randomNumber($scope.max,0)[0]
});
}
return data;
}())
}]
});
And this is the HTML that should update the maximum value:
<button ng-click="max = 10">10</button>
<button ng-click="max = 100">100</button>
<button ng-click="max = 1000">1000</button>
<button ng-click="max = 10000">10000</button>
However, it's not updating the maximum value. Any tips?
Here's a Plunker: http://plnkr.co/edit/N0UfORtSjYW5jaPGojXH?p=preview
You need to redraw the chart when you change the max value.
See the plnkr I watch the max value and when max changes call the draw function.
$scope.draw = function() {
$('#chart').highcharts({
series: [{
data: (function() {
var data = [];
for (var i = 0; i < 60; i++) {
data.push({
x: i,
y: $scope.randomNumber($scope.max, 0)[0]
});
}
return data;
}())
}]
});
}
$scope.draw();
$scope.$watch('max', function() {
$scope.draw();
});
http://plnkr.co/edit/Cp0V46z7UgnRiQsKNrtl?p=preview
The JQgrid I have is generated through JavaScript as I have to show a calendar and corresponding values in it from the JSON. The problem I have is I have to show a count of all the values in the column at the bottom for which I thought Footer row would be a good option.
But the issue is that I am not able to use JavaScript to populate the footer row with the totals of all the values in that column.I want to iterate on the column names and fill each column with its value.
HTML:
<table id="jqGrid"></table>
JavaScript
$(document).ready( function () {
Date.prototype.addDays = function(days) {
var dat = new Date(this.valueOf());
dat.setDate(dat.getDate() + days);
return dat;
};
function GenerateColumns(startDate, stopDate, col, columnType, data) {
var dateArray = col;
var currentDate = startDate;
if(columnType === "cn") {
while (currentDate <= stopDate) {
dateArray.push(moment(currentDate).format('ddd DD'));
currentDate = currentDate.addDays(1);
}
} else {
var i = 0;
while (currentDate <= stopDate) {
dateArray.push({"name": moment(currentDate).format('ddd DD') , "index" : moment(currentDate).format('ddd DD')});
currentDate = currentDate.addDays(1);
i++;
}
}
return dateArray;
}
function countBaseline (columnNames) {
var actualBaseline = [];
columnNames.forEach (function (colnm, index) {
if (index > 3) {
var mydata = $("#jqGrid").jqGrid("getGridParam", "data"),
myColumn = $.map(mydata, function (item) {
return item[colnm];
});
var i = 0;
for (var j = 0; j < myColumn.length;j ++ ) {
if (myColumn[j] !== "NONE") {
i++;
}
}
actualBaseline.push(i);
return;
}
});
return actualBaseline;
}
var $grid = $("#jqGrid");
var cm = [
{name:'EmployeeID',index:'EmployeeID', width:65, sorttype: "int", editable:false,editoptions:{readonly:true,size:10} },
{name:'FirstName', formatter: function (cellvalue, options, rowObject) {
return cellvalue + ' ' + rowObject.LastName;
} },
{name:'EmployeeType'},
{name: 'Competencies'}
];
var cn = ['_id','Name', 'type', 'Competencies'];
$.ajax({
url: 'assets/data/scheduler2.json',
error: function (err, res) {
console.log("test");
},
success: function (result ) {
var startDate, days;
var endDate = moment(result.StartDate).add(result.rows[0].Days.length, 'day');
var day;
var columnNames = GenerateColumns(moment(result.StartDate)._d, endDate._d, cn, "cn"),
columnModels = GenerateColumns(moment(result.StartDate)._d, endDate._d, cm, "cm", result.rows);
var width = $grid.closest(".ui-jqgrid").parent().width();
$grid.jqGrid({
datatype: 'jsonstring',
datastr: result,
jsonReader: {
repeatitems: false
},
colNames: columnNames,
colModel: columnModels ,
width: 1880,
height: 450,
rowList:[10,20,30],
pager: '#jqGridPager',
sortname: 'id',
viewrecords: true,
rowNum: 150,
sortorder: "desc",
caption: result.ScheduleName,
footerrow : true,
userDataOnFooter : true, // use the userData parameter of the JSON response to display data on footer
});
var names = columnNames,
data= result.rows;
var mydata = [];
for (var i = 0; i < data.length; i++) {
mydata[i] = {};
for (var j = 0; j < data[i].Comp.length - 1; j++) {
mydata[i][names[j + 4]] = data[i].Comp[j];
if (names[j + 4].split(" ")[0] === "Sat" || names[j + 4].split(" ")[0] === "Sun")
$('#jqGrid').jqGrid('setCell',i, names[j + 4],"",{'background-color':'#AFEEEE', 'background-image':'none'});
}
}
for (var k = 0; k <= mydata.length; k++) {
$("#jqGrid").jqGrid('setRowData', k + 1, mydata[k], "first");
}
var actual = countBaseline(columnNames);
var i = 0;
columnNames.forEach (function (colnm, index) {
if (i > 3) {
$grid.jqGrid(
"footerData",
"set",
{colnm: actual[index]}
//{"Sun 06": actual[index]}
// {"Sun 06": 54 }
);
}
i++;
});
}
});
});
The main code is the last one, Where I have baseline which is an array of numbers of which I want to populate each value with a corresponding column. What happening is if you see the commented lines "set footerData" is only writing the value on one column but not writing values on all the columns with forEach.
var baseline = countBaseline(columnNames);
var i = 0;
columnNames.forEach (function (colnm, index) {
if (i > 3) {
$grid.jqGrid(
"footerData",
"set",
{colnm: baseline[index]}
// {"Sun 06": baseline[index]}
// {"Sun 06": 54 }
);
}
i++;
});
What I want to achieve: